diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..5ace4600a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 510ae8e7f..9f7799daa 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -43,7 +43,7 @@ jobs: toolchain: ninja-vs-win64-cxx17 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: lukka/get-cmake@latest @@ -64,21 +64,21 @@ jobs: - name: Checkout Hunter toolchains if: endsWith(matrix.name, 'hunter') - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: cpp-pm/polly path: cmake/polly - name: Remove contrib directory for Hunter builds if: contains(matrix.name, 'hunter') - uses: JesseTG/rm@v1.0.2 + uses: JesseTG/rm@v1.0.3 with: path: contrib - name: Cache DX SDK id: dxcache if: contains(matrix.name, 'windows') - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: '${{ github.workspace }}/DX_SDK' key: ${{ runner.os }}-DX_SDK @@ -122,7 +122,7 @@ jobs: run: cd build/bin && ./unit ${{ steps.hunter_extra_test_args.outputs.args }} shell: bash - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 if: matrix.name == 'windows-msvc' with: name: 'assimp-bins-${{ matrix.name }}-${{ github.sha }}' diff --git a/.github/workflows/sanitizer.yml b/.github/workflows/sanitizer.yml index e2cb1cf53..750c17005 100644 --- a/.github/workflows/sanitizer.yml +++ b/.github/workflows/sanitizer.yml @@ -11,7 +11,7 @@ jobs: name: adress-sanitizer runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: lukka/get-cmake@latest - uses: lukka/set-shell-env@v1 with: @@ -35,7 +35,7 @@ jobs: name: undefined-behavior-sanitizer runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: lukka/get-cmake@latest - uses: lukka/set-shell-env@v1 with: diff --git a/Build.md b/Build.md index d6abe7b67..d8e6c50f6 100644 --- a/Build.md +++ b/Build.md @@ -14,7 +14,8 @@ The assimp port in vcpkg is kept up to date by Microsoft team members and commun ## Install on Ubuntu You can install the Asset-Importer-Lib via apt: ``` -sudo apt-get install assimp +sudo apt-get update +sudo apt-get install libassimp-dev ``` ## Install pyassimp diff --git a/CMakeLists.txt b/CMakeLists.txt index 2aa66421c..a4f711528 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,7 +90,7 @@ OPTION( ASSIMP_BUILD_ZLIB ) OPTION( ASSIMP_BUILD_ASSIMP_TOOLS "If the supplementary tools for Assimp are built in addition to the library." - ON + OFF ) OPTION ( ASSIMP_BUILD_SAMPLES "If the official samples are built as well (needs Glut)." diff --git a/code/AssetLib/3MF/3MFXmlTags.h b/code/AssetLib/3MF/3MFXmlTags.h index 63f18b455..333d169aa 100644 --- a/code/AssetLib/3MF/3MFXmlTags.h +++ b/code/AssetLib/3MF/3MFXmlTags.h @@ -74,6 +74,8 @@ namespace XmlTag { const char* const pid = "pid"; const char* const pindex = "pindex"; const char* const p1 = "p1"; + const char *const p2 = "p2"; + const char *const p3 = "p3"; const char* const name = "name"; const char* const type = "type"; const char* const build = "build"; diff --git a/code/AssetLib/3MF/D3MFOpcPackage.cpp b/code/AssetLib/3MF/D3MFOpcPackage.cpp index f88039ae8..a2182dc29 100644 --- a/code/AssetLib/3MF/D3MFOpcPackage.cpp +++ b/code/AssetLib/3MF/D3MFOpcPackage.cpp @@ -186,6 +186,9 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) : D3MFOpcPackage::~D3MFOpcPackage() { mZipArchive->Close(mRootStream); delete mZipArchive; + for (auto tex : mEmbeddedTextures) { + delete tex; + } } IOStream *D3MFOpcPackage::RootStream() const { diff --git a/code/AssetLib/3MF/XmlSerializer.cpp b/code/AssetLib/3MF/XmlSerializer.cpp index 740bc5658..043ac84cc 100644 --- a/code/AssetLib/3MF/XmlSerializer.cpp +++ b/code/AssetLib/3MF/XmlSerializer.cpp @@ -64,7 +64,7 @@ bool validateColorString(const char *color) { return true; } -aiFace ReadTriangle(XmlNode &node) { +aiFace ReadTriangle(XmlNode &node, int &texId0, int &texId1, int &texId2) { aiFace face; face.mNumIndices = 3; @@ -73,6 +73,11 @@ aiFace ReadTriangle(XmlNode &node) { face.mIndices[1] = static_cast(std::atoi(node.attribute(XmlTag::v2).as_string())); face.mIndices[2] = static_cast(std::atoi(node.attribute(XmlTag::v3).as_string())); + texId0 = texId1 = texId2 = -1; + XmlParser::getIntAttribute(node, XmlTag::p1, texId0); + XmlParser::getIntAttribute(node, XmlTag::p2, texId1); + XmlParser::getIntAttribute(node, XmlTag::p3, texId2); + return face; } @@ -412,6 +417,9 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) { bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid); bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1); + int texId[3]; + Texture2DGroup *group = nullptr; + aiFace face = ReadTriangle(currentNode, texId[0], texId[1], texId[2]); if (hasPid && hasP1) { auto it = mResourcesDictionnary.find(pid); if (it != mResourcesDictionnary.end()) { @@ -420,23 +428,34 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) { mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1]; } else if (it->second->getType() == ResourceType::RT_Texture2DGroup) { if (mesh->mTextureCoords[0] == nullptr) { - Texture2DGroup *group = static_cast(it->second); + mesh->mNumUVComponents[0] = 2; + for (unsigned int i = 1; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { + mesh->mNumUVComponents[i] = 0; + } + + group = static_cast(it->second); const std::string name = ai_to_string(group->mTexId); for (size_t i = 0; i < mMaterials.size(); ++i) { if (name == mMaterials[i]->GetName().C_Str()) { mesh->mMaterialIndex = static_cast(i); } } - mesh->mTextureCoords[0] = new aiVector3D[group->mTex2dCoords.size()]; - for (unsigned int i = 0; i < group->mTex2dCoords.size(); ++i) { - mesh->mTextureCoords[0][i] = aiVector3D(group->mTex2dCoords[i].x, group->mTex2dCoords[i].y, 0); - } + mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]; } } } } - aiFace face = ReadTriangle(currentNode); + // Load texture coordinates into mesh, when any + if (group != nullptr) { + size_t i0 = face.mIndices[0]; + size_t i1 = face.mIndices[1]; + size_t i2 = face.mIndices[2]; + mesh->mTextureCoords[0][i0] = aiVector3D(group->mTex2dCoords[texId[0]].x, group->mTex2dCoords[texId[0]].y, 0.0f); + mesh->mTextureCoords[0][i1] = aiVector3D(group->mTex2dCoords[texId[1]].x, group->mTex2dCoords[texId[1]].y, 0.0f); + mesh->mTextureCoords[0][i2] = aiVector3D(group->mTex2dCoords[texId[2]].x, group->mTex2dCoords[texId[2]].y, 0.0f); + } + faces.push_back(face); } } @@ -578,11 +597,15 @@ aiMaterial *XmlSerializer::readMaterialDef(XmlNode &node, unsigned int basemater } void XmlSerializer::StoreMaterialsInScene(aiScene *scene) { - if (nullptr == scene || mMaterials.empty()) { + if (nullptr == scene) { return; } scene->mNumMaterials = static_cast(mMaterials.size()); + if (scene->mNumMaterials == 0) { + return; + } + scene->mMaterials = new aiMaterial *[scene->mNumMaterials]; for (size_t i = 0; i < mMaterials.size(); ++i) { scene->mMaterials[i] = mMaterials[i]; diff --git a/code/AssetLib/Collada/ColladaHelper.h b/code/AssetLib/Collada/ColladaHelper.h index 31d7b5ae5..2930f5108 100644 --- a/code/AssetLib/Collada/ColladaHelper.h +++ b/code/AssetLib/Collada/ColladaHelper.h @@ -621,6 +621,11 @@ struct Animation { for (std::vector::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();) { Animation *anim = *it; + // Assign the first animation name to the parent if empty. + // This prevents the animation name from being lost when animations are combined + if (mName.empty()) { + mName = anim->mName; + } CombineSingleChannelAnimationsRecursively(anim); if (childrenAnimationsHaveDifferentChannels && anim->mChannels.size() == 1 && diff --git a/code/AssetLib/Collada/ColladaLoader.cpp b/code/AssetLib/Collada/ColladaLoader.cpp index 775ba44d2..fdc9c1c8f 100644 --- a/code/AssetLib/Collada/ColladaLoader.cpp +++ b/code/AssetLib/Collada/ColladaLoader.cpp @@ -102,6 +102,7 @@ ColladaLoader::ColladaLoader() : mTextures(), mAnims(), noSkeletonMesh(false), + removeEmptyBones(false), ignoreUpDirection(false), useColladaName(false), mNodeNameCounter(0) { @@ -130,6 +131,7 @@ bool ColladaLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool // ------------------------------------------------------------------------------------------------ void ColladaLoader::SetupProperties(const Importer *pImp) { noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES, 0) != 0; + removeEmptyBones = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true) != 0; ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION, 0) != 0; useColladaName = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES, 0) != 0; } @@ -798,9 +800,10 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc // count the number of bones which influence vertices of the current submesh size_t numRemainingBones = 0; for (const auto & dstBone : dstBones) { - if (!dstBone.empty()) { - ++numRemainingBones; + if (dstBone.empty() && removeEmptyBones) { + continue; } + ++numRemainingBones; } // create bone array and copy bone weights one by one @@ -809,7 +812,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc size_t boneCount = 0; for (size_t a = 0; a < numBones; ++a) { // omit bones without weights - if (dstBones[a].empty()) { + if (dstBones[a].empty() && removeEmptyBones) { continue; } diff --git a/code/AssetLib/Collada/ColladaLoader.h b/code/AssetLib/Collada/ColladaLoader.h index 246abed22..870c12a5a 100644 --- a/code/AssetLib/Collada/ColladaLoader.h +++ b/code/AssetLib/Collada/ColladaLoader.h @@ -237,6 +237,7 @@ protected: std::vector mAnims; bool noSkeletonMesh; + bool removeEmptyBones; bool ignoreUpDirection; bool useColladaName; diff --git a/code/AssetLib/DXF/DXFLoader.cpp b/code/AssetLib/DXF/DXFLoader.cpp index 6b2dbbe82..2f1ec35b4 100644 --- a/code/AssetLib/DXF/DXFLoader.cpp +++ b/code/AssetLib/DXF/DXFLoader.cpp @@ -368,7 +368,9 @@ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& bloc // XXX this would be the place to implement recursive expansion if needed. const DXF::Block& bl_src = *(*it).second; - for (std::shared_ptr pl_in : bl_src.lines) { + const size_t size = bl_src.lines.size(); // the size may increase in the loop + for (size_t i = 0; i < size; ++i) { + std::shared_ptr pl_in = bl_src.lines[i]; if (!pl_in) { ASSIMP_LOG_ERROR("DXF: PolyLine instance is nullptr, skipping."); continue; diff --git a/code/AssetLib/FBX/FBXConverter.cpp b/code/AssetLib/FBX/FBXConverter.cpp index 83d95dada..3ae96d54d 100644 --- a/code/AssetLib/FBX/FBXConverter.cpp +++ b/code/AssetLib/FBX/FBXConverter.cpp @@ -3377,6 +3377,10 @@ FBXConverter::KeyFrameListList FBXConverter::GetRotationKeyframeList(const std:: Keys->push_back(tnew); Values->push_back(vnew); } + else { + // Something broke + break; + } tp = tnew; vp = vnew; } diff --git a/code/AssetLib/Irr/IRRLoader.cpp b/code/AssetLib/Irr/IRRLoader.cpp index 0061634a6..b16565559 100644 --- a/code/AssetLib/Irr/IRRLoader.cpp +++ b/code/AssetLib/Irr/IRRLoader.cpp @@ -874,7 +874,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy // Batch loader used to load external models BatchLoader batch(pIOHandler); - // batch.SetBasePath(pFile); + //batch.SetBasePath(pFile); cameras.reserve(5); lights.reserve(5); diff --git a/code/AssetLib/LWO/LWOLoader.cpp b/code/AssetLib/LWO/LWOLoader.cpp index c4e85bc50..44517a1a6 100644 --- a/code/AssetLib/LWO/LWOLoader.cpp +++ b/code/AssetLib/LWO/LWOLoader.cpp @@ -287,7 +287,7 @@ void LWOImporter::InternReadFile(const std::string &pFile, if (UINT_MAX == iDefaultSurface) { pSorted.erase(pSorted.end() - 1); } - for (unsigned int p = 0, j = 0; j < mSurfaces->size(); ++j) { + for (unsigned int j = 0; j < mSurfaces->size(); ++j) { SortedRep &sorted = pSorted[j]; if (sorted.empty()) continue; @@ -425,7 +425,6 @@ void LWOImporter::InternReadFile(const std::string &pFile, } else { ASSIMP_LOG_VERBOSE_DEBUG("LWO2: No need to compute normals, they're already there"); } - ++p; } } diff --git a/code/AssetLib/LWS/LWSLoader.cpp b/code/AssetLib/LWS/LWSLoader.cpp index 951dbe180..abaaaa305 100644 --- a/code/AssetLib/LWS/LWSLoader.cpp +++ b/code/AssetLib/LWS/LWSLoader.cpp @@ -313,6 +313,9 @@ void LWSImporter::SetupNodeName(aiNode *nd, LWS::NodeDesc &src) { std::string::size_type t = src.path.substr(s).find_last_of('.'); nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)", src.path.substr(s).substr(0, t).c_str(), combined); + if (nd->mName.length > MAXLEN) { + nd->mName.length = MAXLEN; + } return; } } diff --git a/code/AssetLib/MDL/MDLMaterialLoader.cpp b/code/AssetLib/MDL/MDLMaterialLoader.cpp index 2de43d241..db4b534f2 100644 --- a/code/AssetLib/MDL/MDLMaterialLoader.cpp +++ b/code/AssetLib/MDL/MDLMaterialLoader.cpp @@ -449,6 +449,9 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7( unsigned int iWidth, unsigned int iHeight) { std::unique_ptr pcNew; + if (szCurrent == nullptr) { + return; + } // get the type of the skin unsigned int iMasked = (unsigned int)(iType & 0xF); diff --git a/code/AssetLib/NDO/NDOLoader.cpp b/code/AssetLib/NDO/NDOLoader.cpp index 37c543692..07953b04d 100644 --- a/code/AssetLib/NDO/NDOLoader.cpp +++ b/code/AssetLib/NDO/NDOLoader.cpp @@ -136,7 +136,9 @@ void NDOImporter::InternReadFile( const std::string& pFile, ASSIMP_LOG_INFO("NDO file format is 1.2"); } else { - ASSIMP_LOG_WARN( "Unrecognized nendo file format version, continuing happily ... :", (head+6)); + char buff[4] = {0}; + memcpy(buff, head+6, 3); + ASSIMP_LOG_WARN( "Unrecognized nendo file format version, continuing happily ... :", buff); } reader.IncPtr(2); /* skip flags */ diff --git a/code/AssetLib/Obj/ObjFileMtlImporter.cpp b/code/AssetLib/Obj/ObjFileMtlImporter.cpp index a73277701..f8ab1b69e 100644 --- a/code/AssetLib/Obj/ObjFileMtlImporter.cpp +++ b/code/AssetLib/Obj/ObjFileMtlImporter.cpp @@ -126,17 +126,21 @@ void ObjFileMtlImporter::load() { if (*m_DataIt == 'a') // Ambient color { ++m_DataIt; - getColorRGBA(&m_pModel->m_pCurrentMaterial->ambient); + if (m_pModel->m_pCurrentMaterial != nullptr) + getColorRGBA(&m_pModel->m_pCurrentMaterial->ambient); } else if (*m_DataIt == 'd') { // Diffuse color ++m_DataIt; - getColorRGBA(&m_pModel->m_pCurrentMaterial->diffuse); + if (m_pModel->m_pCurrentMaterial != nullptr) + getColorRGBA(&m_pModel->m_pCurrentMaterial->diffuse); } else if (*m_DataIt == 's') { ++m_DataIt; - getColorRGBA(&m_pModel->m_pCurrentMaterial->specular); + if (m_pModel->m_pCurrentMaterial != nullptr) + getColorRGBA(&m_pModel->m_pCurrentMaterial->specular); } else if (*m_DataIt == 'e') { ++m_DataIt; - getColorRGBA(&m_pModel->m_pCurrentMaterial->emissive); + if (m_pModel->m_pCurrentMaterial != nullptr) + getColorRGBA(&m_pModel->m_pCurrentMaterial->emissive); } m_DataIt = skipLine(m_DataIt, m_DataItEnd, m_uiLine); } break; @@ -145,13 +149,15 @@ void ObjFileMtlImporter::load() { // Material transmission color if (*m_DataIt == 'f') { ++m_DataIt; - getColorRGBA(&m_pModel->m_pCurrentMaterial->transparent); + if (m_pModel->m_pCurrentMaterial != nullptr) + getColorRGBA(&m_pModel->m_pCurrentMaterial->transparent); } else if (*m_DataIt == 'r') { // Material transmission alpha value ++m_DataIt; ai_real d; getFloatValue(d); - m_pModel->m_pCurrentMaterial->alpha = static_cast(1.0) - d; + if (m_pModel->m_pCurrentMaterial != nullptr) + m_pModel->m_pCurrentMaterial->alpha = static_cast(1.0) - d; } m_DataIt = skipLine(m_DataIt, m_DataItEnd, m_uiLine); } break; @@ -162,7 +168,8 @@ void ObjFileMtlImporter::load() { } else { // Alpha value ++m_DataIt; - getFloatValue(m_pModel->m_pCurrentMaterial->alpha); + if (m_pModel->m_pCurrentMaterial != nullptr) + getFloatValue(m_pModel->m_pCurrentMaterial->alpha); m_DataIt = skipLine(m_DataIt, m_DataItEnd, m_uiLine); } } break; @@ -173,11 +180,13 @@ void ObjFileMtlImporter::load() { switch (*m_DataIt) { case 's': // Specular exponent ++m_DataIt; - getFloatValue(m_pModel->m_pCurrentMaterial->shineness); + if (m_pModel->m_pCurrentMaterial != nullptr) + getFloatValue(m_pModel->m_pCurrentMaterial->shineness); break; case 'i': // Index Of refraction ++m_DataIt; - getFloatValue(m_pModel->m_pCurrentMaterial->ior); + if (m_pModel->m_pCurrentMaterial != nullptr) + getFloatValue(m_pModel->m_pCurrentMaterial->ior); break; case 'e': // New material createMaterial(); @@ -197,23 +206,28 @@ void ObjFileMtlImporter::load() { { case 'r': ++m_DataIt; - getFloatValue(m_pModel->m_pCurrentMaterial->roughness); + if (m_pModel->m_pCurrentMaterial != nullptr) + getFloatValue(m_pModel->m_pCurrentMaterial->roughness); break; case 'm': ++m_DataIt; - getFloatValue(m_pModel->m_pCurrentMaterial->metallic); + if (m_pModel->m_pCurrentMaterial != nullptr) + getFloatValue(m_pModel->m_pCurrentMaterial->metallic); break; case 's': ++m_DataIt; - getColorRGBA(m_pModel->m_pCurrentMaterial->sheen); + if (m_pModel->m_pCurrentMaterial != nullptr) + getColorRGBA(m_pModel->m_pCurrentMaterial->sheen); break; case 'c': ++m_DataIt; if (*m_DataIt == 'r') { ++m_DataIt; - getFloatValue(m_pModel->m_pCurrentMaterial->clearcoat_roughness); + if (m_pModel->m_pCurrentMaterial != nullptr) + getFloatValue(m_pModel->m_pCurrentMaterial->clearcoat_roughness); } else { - getFloatValue(m_pModel->m_pCurrentMaterial->clearcoat_thickness); + if (m_pModel->m_pCurrentMaterial != nullptr) + getFloatValue(m_pModel->m_pCurrentMaterial->clearcoat_thickness); } break; } @@ -232,7 +246,8 @@ void ObjFileMtlImporter::load() { case 'i': // Illumination model { m_DataIt = getNextToken(m_DataIt, m_DataItEnd); - getIlluminationModel(m_pModel->m_pCurrentMaterial->illumination_model); + if (m_pModel->m_pCurrentMaterial != nullptr) + getIlluminationModel(m_pModel->m_pCurrentMaterial->illumination_model); m_DataIt = skipLine(m_DataIt, m_DataItEnd, m_uiLine); } break; @@ -240,7 +255,8 @@ void ObjFileMtlImporter::load() { { ++m_DataIt; getFloatValue(m_pModel->m_pCurrentMaterial->anisotropy); - m_DataIt = skipLine(m_DataIt, m_DataItEnd, m_uiLine); + if (m_pModel->m_pCurrentMaterial != nullptr) + m_DataIt = skipLine(m_DataIt, m_DataItEnd, m_uiLine); } break; default: { diff --git a/code/AssetLib/Obj/ObjFileParser.cpp b/code/AssetLib/Obj/ObjFileParser.cpp index 4e50d5dae..4dc08edbc 100644 --- a/code/AssetLib/Obj/ObjFileParser.cpp +++ b/code/AssetLib/Obj/ObjFileParser.cpp @@ -458,7 +458,8 @@ void ObjFileParser::getFace(aiPrimitiveType type) { iPos = 0; } else { //OBJ USES 1 Base ARRAYS!!!! - const int iVal(::atoi(&(*m_DataIt))); + std::string number(&(*m_DataIt), m_DataItEnd - m_DataIt); + const int iVal(::atoi(number.c_str())); // increment iStep position based off of the sign and # of digits int tmp = iVal; diff --git a/code/AssetLib/OpenGEX/OpenGEXImporter.cpp b/code/AssetLib/OpenGEX/OpenGEXImporter.cpp index c8e47933d..2883f9612 100644 --- a/code/AssetLib/OpenGEX/OpenGEXImporter.cpp +++ b/code/AssetLib/OpenGEX/OpenGEXImporter.cpp @@ -151,45 +151,46 @@ namespace Grammar { } static TokenType matchTokenType(const char *tokenType) { - if (MetricType == tokenType) { + const size_t len = std::strlen(tokenType); + if (0 == strncmp(MetricType, tokenType, len)) { return MetricToken; - } else if (NameType == tokenType) { + } else if (0 == strncmp(NameType, tokenType, len)) { return NameToken; - } else if (ObjectRefType == tokenType) { + } else if (0 == strncmp(ObjectRefType, tokenType, len)) { return ObjectRefToken; - } else if (MaterialRefType == tokenType) { + } else if (0 == strncmp(MaterialRefType, tokenType, len)) { return MaterialRefToken; - } else if (MetricKeyType == tokenType) { + } else if (0 == strncmp(MetricKeyType, tokenType, len)) { return MetricKeyToken; - } else if (GeometryNodeType == tokenType) { + } else if (0 == strncmp(GeometryNodeType, tokenType, len)) { return GeometryNodeToken; - } else if (CameraNodeType == tokenType) { + } else if (0 == strncmp(CameraNodeType, tokenType, len)) { return CameraNodeToken; - } else if (LightNodeType == tokenType) { + } else if (0 == strncmp(LightNodeType, tokenType, len)) { return LightNodeToken; - } else if (GeometryObjectType == tokenType) { + } else if (0 == strncmp(GeometryObjectType, tokenType, len)) { return GeometryObjectToken; - } else if (CameraObjectType == tokenType) { + } else if (0 == strncmp(CameraObjectType, tokenType, len)) { return CameraObjectToken; - } else if (LightObjectType == tokenType) { + } else if (0 == strncmp(LightObjectType, tokenType, len)) { return LightObjectToken; - } else if (TransformType == tokenType) { + } else if (0 == strncmp(TransformType, tokenType, len)) { return TransformToken; - } else if (MeshType == tokenType) { + } else if (0 == strncmp(MeshType, tokenType, len)) { return MeshToken; - } else if (VertexArrayType == tokenType) { + } else if (0 == strncmp(VertexArrayType, tokenType, len)) { return VertexArrayToken; - } else if (IndexArrayType == tokenType) { + } else if (0 == strncmp(IndexArrayType, tokenType, len)) { return IndexArrayToken; - } else if (MaterialType == tokenType) { + } else if (0 == strncmp(MaterialType, tokenType, len)) { return MaterialToken; - } else if (ColorType == tokenType) { + } else if (0 == strncmp(ColorType, tokenType, len)) { return ColorToken; - } else if (ParamType == tokenType) { + } else if (0 == strncmp(ParamType, tokenType, len)) { return ParamToken; - } else if (TextureType == tokenType) { + } else if (0 == strncmp(TextureType, tokenType, len)) { return TextureToken; - } else if (AttenType == tokenType) { + } else if (0 == strncmp(AttenType, tokenType, len)) { return AttenToken; } @@ -256,11 +257,6 @@ OpenGEXImporter::RefInfo::RefInfo(aiNode *node, Type type, std::vector m_Names; RefInfo( aiNode *node, Type type, std::vector &names ); - ~RefInfo(); + ~RefInfo() = default; RefInfo( const RefInfo & ) = delete; RefInfo &operator = ( const RefInfo & ) = delete; diff --git a/code/AssetLib/Q3D/Q3DLoader.cpp b/code/AssetLib/Q3D/Q3DLoader.cpp index c773bbfcd..0bfe16162 100644 --- a/code/AssetLib/Q3D/Q3DLoader.cpp +++ b/code/AssetLib/Q3D/Q3DLoader.cpp @@ -129,10 +129,20 @@ void Q3DImporter::InternReadFile(const std::string &pFile, unsigned int numTextures = (unsigned int)stream.GetI4(); std::vector materials; - materials.reserve(numMats); + try { + materials.reserve(numMats); + } catch(const std::bad_alloc&) { + ASSIMP_LOG_ERROR("Invalid alloc for materials."); + throw DeadlyImportError("Invalid Quick3D-file, material allocation failed."); + } std::vector meshes; - meshes.reserve(numMeshes); + try { + meshes.reserve(numMeshes); + } catch(const std::bad_alloc&) { + ASSIMP_LOG_ERROR("Invalid alloc for meshes."); + throw DeadlyImportError("Invalid Quick3D-file, mesh allocation failed."); + } // Allocate the scene root node pScene->mRootNode = new aiNode(); diff --git a/code/AssetLib/STL/STLLoader.cpp b/code/AssetLib/STL/STLLoader.cpp index 8de57f1ee..cea448de1 100644 --- a/code/AssetLib/STL/STLLoader.cpp +++ b/code/AssetLib/STL/STLLoader.cpp @@ -73,7 +73,7 @@ static const aiImporterDesc desc = { // 1) 80 byte header // 2) 4 byte face count // 3) 50 bytes per face -static bool IsBinarySTL(const char *buffer, unsigned int fileSize) { +static bool IsBinarySTL(const char *buffer, size_t fileSize) { if (fileSize < 84) { return false; } @@ -92,7 +92,7 @@ static const char UnicodeBoundary = 127; // An ascii STL buffer will begin with "solid NAME", where NAME is optional. // Note: The "solid NAME" check is necessary, but not sufficient, to determine // if the buffer is ASCII; a binary header could also begin with "solid NAME". -static bool IsAsciiSTL(const char *buffer, unsigned int fileSize) { +static bool IsAsciiSTL(const char *buffer, size_t fileSize) { if (IsBinarySTL(buffer, fileSize)) return false; @@ -172,7 +172,7 @@ void STLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy throw DeadlyImportError("Failed to open STL file ", pFile, "."); } - mFileSize = (unsigned int)file->FileSize(); + mFileSize = file->FileSize(); // allocate storage and copy the contents of the file to a memory buffer // (terminate it with zero) @@ -233,7 +233,7 @@ void STLImporter::LoadASCIIFile(aiNode *root) { // try to guess how many vertices we could have // assume we'll need 160 bytes for each face - size_t sizeEstimate = std::max(1u, mFileSize / 160u) * 3; + size_t sizeEstimate = std::max(1ull, mFileSize / 160ull) * 3ull; positionBuffer.reserve(sizeEstimate); normalBuffer.reserve(sizeEstimate); @@ -284,8 +284,6 @@ void STLImporter::LoadASCIIFile(aiNode *root) { ASSIMP_LOG_WARN("STL: A new facet begins but the old is not yet complete"); } faceVertexCounter = 0; - normalBuffer.push_back(aiVector3D()); - aiVector3D *vn = &normalBuffer.back(); sz += 6; SkipSpaces(&sz); @@ -295,15 +293,17 @@ void STLImporter::LoadASCIIFile(aiNode *root) { if (sz[6] == '\0') { throw DeadlyImportError("STL: unexpected EOF while parsing facet"); } + aiVector3D vn; sz += 7; SkipSpaces(&sz); - sz = fast_atoreal_move(sz, (ai_real &)vn->x); + sz = fast_atoreal_move(sz, (ai_real &)vn.x); SkipSpaces(&sz); - sz = fast_atoreal_move(sz, (ai_real &)vn->y); + sz = fast_atoreal_move(sz, (ai_real &)vn.y); SkipSpaces(&sz); - sz = fast_atoreal_move(sz, (ai_real &)vn->z); - normalBuffer.push_back(*vn); - normalBuffer.push_back(*vn); + sz = fast_atoreal_move(sz, (ai_real &)vn.z); + normalBuffer.emplace_back(vn); + normalBuffer.emplace_back(vn); + normalBuffer.emplace_back(vn); } } else if (!strncmp(sz, "vertex", 6) && ::IsSpaceOrNewLine(*(sz + 6))) { // vertex 1.50000 1.50000 0.00000 if (faceVertexCounter >= 3) { @@ -315,7 +315,7 @@ void STLImporter::LoadASCIIFile(aiNode *root) { } sz += 7; SkipSpaces(&sz); - positionBuffer.push_back(aiVector3D()); + positionBuffer.emplace_back(); aiVector3D *vn = &positionBuffer.back(); sz = fast_atoreal_move(sz, (ai_real &)vn->x); SkipSpaces(&sz); @@ -439,7 +439,7 @@ bool STLImporter::LoadBinaryFile() { pMesh->mNumFaces = *((uint32_t *)sz); sz += 4; - if (mFileSize < 84 + pMesh->mNumFaces * 50) { + if (mFileSize < 84ull + pMesh->mNumFaces * 50ull) { throw DeadlyImportError("STL: file is too small to hold all facets"); } @@ -517,13 +517,13 @@ bool STLImporter::LoadBinaryFile() { const ai_real invVal((ai_real)1.0 / (ai_real)31.0); if (bIsMaterialise) // this is reversed { - clr->r = (color & 0x31u) * invVal; - clr->g = ((color & (0x31u << 5)) >> 5u) * invVal; - clr->b = ((color & (0x31u << 10)) >> 10u) * invVal; + clr->r = (color & 0x1fu) * invVal; + clr->g = ((color & (0x1fu << 5)) >> 5u) * invVal; + clr->b = ((color & (0x1fu << 10)) >> 10u) * invVal; } else { - clr->b = (color & 0x31u) * invVal; - clr->g = ((color & (0x31u << 5)) >> 5u) * invVal; - clr->r = ((color & (0x31u << 10)) >> 10u) * invVal; + clr->b = (color & 0x1fu) * invVal; + clr->g = ((color & (0x1fu << 5)) >> 5u) * invVal; + clr->r = ((color & (0x1fu << 10)) >> 10u) * invVal; } // assign the color to all vertices of the face *(clr + 1) = *clr; diff --git a/code/AssetLib/STL/STLLoader.h b/code/AssetLib/STL/STLLoader.h index a340abe6b..0be6a95f0 100644 --- a/code/AssetLib/STL/STLLoader.h +++ b/code/AssetLib/STL/STLLoader.h @@ -109,7 +109,7 @@ protected: const char* mBuffer; /** Size of the file, in bytes */ - unsigned int mFileSize; + size_t mFileSize; /** Output scene */ aiScene* mScene; diff --git a/code/AssetLib/Step/STEPFile.h b/code/AssetLib/Step/STEPFile.h index e09faad98..ce7b357ad 100644 --- a/code/AssetLib/Step/STEPFile.h +++ b/code/AssetLib/Step/STEPFile.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2020, assimp team - +Copyright (c) 2006-2022, assimp team All rights reserved. @@ -59,7 +58,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # pragma warning(disable : 4127 4456 4245 4512 ) #endif // _MSC_VER -// #if _MSC_VER > 1500 || (defined __GNUC___) # define ASSIMP_STEP_USE_UNORDERED_MULTIMAP #else @@ -99,13 +97,9 @@ namespace EXPRESS { class DataType; class UNSET; /*: public DataType */ class ISDERIVED; /*: public DataType */ -// class REAL; /*: public DataType */ class ENUM; /*: public DataType */ -// class STRING; /*: public DataType */ -// class INTEGER; /*: public DataType */ class ENTITY; /*: public DataType */ class LIST; /*: public DataType */ -// class SELECT; /*: public DataType */ // a conversion schema is not exactly an EXPRESS schema, rather it // is a list of pointers to conversion functions to build up the @@ -127,7 +121,8 @@ namespace STEP { // ------------------------------------------------------------------------------- /** Exception class used by the STEP loading & parsing code. It is typically - * coupled with a line number. */ + * coupled with a line number. + */ // ------------------------------------------------------------------------------- struct SyntaxError : DeadlyImportError { enum : uint64_t { @@ -139,8 +134,9 @@ struct SyntaxError : DeadlyImportError { // ------------------------------------------------------------------------------- /** Exception class used by the STEP loading & parsing code when a type - * error (i.e. an entity expects a string but receives a bool) occurs. - * It is typically coupled with both an entity id and a line number.*/ + * error (i.e. an entity expects a string but receives a bool) occurs. + * It is typically coupled with both an entity id and a line number. + */ // ------------------------------------------------------------------------------- struct TypeError : DeadlyImportError { enum : uint64_t { @@ -167,10 +163,8 @@ public: typedef std::shared_ptr Out; public: - virtual ~DataType() { - } + virtual ~DataType() = default; -public: template const T &To() const { return dynamic_cast(*this); @@ -206,16 +200,14 @@ public: public: /** parse a variable from a string and set 'inout' to the character - * behind the last consumed character. An optional schema enables, - * if specified, automatic conversion of custom data types. - * - * @throw SyntaxError - */ + * behind the last consumed character. An optional schema enables, + * if specified, automatic conversion of custom data types. + * + * @throw SyntaxError + */ static std::shared_ptr Parse(const char *&inout, uint64_t line = SyntaxError::LINE_NOT_SPECIFIED, const EXPRESS::ConversionSchema *schema = NULL); - -public: }; typedef DataType SELECT; @@ -238,7 +230,8 @@ private: }; // ------------------------------------------------------------------------------- -/** Shared implementation for some of the primitive data type, i.e. int, float */ +/** Shared implementation for some of the primitive data type, i.e. int, float + */ // ------------------------------------------------------------------------------- template class PrimitiveDataType : public DataType { @@ -247,7 +240,7 @@ public: // expose this data type to the user. typedef T Out; - PrimitiveDataType() {} + PrimitiveDataType() = default; PrimitiveDataType(const T &val) : val(val) {} @@ -280,28 +273,18 @@ class ENUMERATION : public STRING { public: ENUMERATION(const std::string &val) : STRING(val) {} - -private: }; typedef ENUMERATION BOOLEAN; // ------------------------------------------------------------------------------- -/** This is just a reference to an entity/object somewhere else */ +/** This is just a reference to an entity/object somewhere else + */ // ------------------------------------------------------------------------------- class ENTITY : public PrimitiveDataType { public: - ENTITY(uint64_t val) : - PrimitiveDataType(val) { - ai_assert(val != 0); - } - - ENTITY() : - PrimitiveDataType(TypeError::ENTITY_NOT_SPECIFIED) { - // empty - } - -private: + ENTITY(uint64_t val) : PrimitiveDataType(val) {} + ENTITY() : PrimitiveDataType(TypeError::ENTITY_NOT_SPECIFIED) {} }; // ------------------------------------------------------------------------------- @@ -319,7 +302,8 @@ public: } public: - /** @see DaraType::Parse */ + /** @see DaraType::Parse + */ static std::shared_ptr Parse(const char *&inout, uint64_t line = SyntaxError::LINE_NOT_SPECIFIED, const EXPRESS::ConversionSchema *schema = NULL); @@ -331,29 +315,20 @@ private: class BINARY : public PrimitiveDataType { public: - BINARY(uint32_t val) : - PrimitiveDataType(val) { - // empty - } - - BINARY() : - PrimitiveDataType(TypeError::ENTITY_NOT_SPECIFIED_32) { - // empty - } + BINARY(uint32_t val) : PrimitiveDataType(val) {} + BINARY() : PrimitiveDataType(TypeError::ENTITY_NOT_SPECIFIED_32) {} }; // ------------------------------------------------------------------------------- /* Not exactly a full EXPRESS schema but rather a list of conversion functions - * to extract valid C++ objects out of a STEP file. Those conversion functions - * may, however, perform further schema validations. */ + * to extract valid C++ objects out of a STEP file. Those conversion functions + * may, however, perform further schema validations. + */ // ------------------------------------------------------------------------------- class ConversionSchema { public: struct SchemaEntry { - SchemaEntry(const char *name, ConvertObjectProc func) : - mName(name), mFunc(func) { - // empty - } + SchemaEntry(const char *name, ConvertObjectProc func) : mName(name), mFunc(func) {} const char *mName; ConvertObjectProc mFunc; @@ -366,8 +341,7 @@ public: *this = schemas; } - ConversionSchema() { - } + ConversionSchema() = default; ConvertObjectProc GetConverterProc(const std::string &name) const { ConverterMap::const_iterator it = converters.find(name); @@ -399,8 +373,9 @@ private: // ------------------------------------------------------------------------------ /** Bundle all the relevant info from a STEP header, parts of which may later - * be plainly dumped to the logfile, whereas others may help the caller pick an - * appropriate loading strategy.*/ + * be plainly dumped to the logfile, whereas others may help the caller pick an + * appropriate loading strategy. + */ // ------------------------------------------------------------------------------ struct HeaderInfo { std::string timestamp; @@ -409,18 +384,14 @@ struct HeaderInfo { }; // ------------------------------------------------------------------------------ -/** Base class for all concrete object instances */ +/** Base class for all concrete object instances + */ // ------------------------------------------------------------------------------ class Object { public: - Object(const char *classname = "unknown") : - id(0), classname(classname) { - // empty - } + Object(const char *classname = "unknown") : id(0), classname(classname) {} - virtual ~Object() { - // empty - } + virtual ~Object() = default; // utilities to simplify casting to concrete types template @@ -469,26 +440,15 @@ size_t GenericFill(const STEP::DB &db, const EXPRESS::LIST ¶ms, T *in); // ------------------------------------------------------------------------------ template struct ObjectHelper : virtual Object { - ObjectHelper() : - aux_is_derived(0) { - // empty - } + ObjectHelper() : aux_is_derived(0) {} static Object *Construct(const STEP::DB &db, const EXPRESS::LIST ¶ms) { // make sure we don't leak if Fill() throws an exception std::unique_ptr impl(new TDerived()); // GenericFill is undefined so we need to have a specialization - const size_t num_args = GenericFill(db, params, &*impl); - (void)num_args; + static_cast(GenericFill(db, params, &*impl)); - // the following check is commented because it will always trigger if - // parts of the entities are generated with dummy wrapper code. - // This is currently done to reduce the size of the loader - // code. - //if (num_args != params.GetSize() && impl->GetClassName() != "NotImplemented") { - // DefaultLogger::get()->debug("STEP: not all parameters consumed"); - //} return impl.release(); } @@ -502,15 +462,9 @@ struct ObjectHelper : virtual Object { // ------------------------------------------------------------------------------ template struct Maybe { - Maybe() : - have() { - // empty - } + Maybe() : have() {} - explicit Maybe(const T &ptr) : - ptr(ptr), have(true) { - // empty - } + explicit Maybe(const T &ptr) : ptr(ptr), have(true) {} void flag_invalid() { have = false; @@ -557,7 +511,8 @@ private: // ------------------------------------------------------------------------------ /** A LazyObject is created when needed. Before this happens, we just keep - the text line that contains the object definition. */ + * the text line that contains the object definition. + */ // ------------------------------------------------------------------------------- class LazyObject { friend class DB; @@ -649,10 +604,7 @@ inline bool operator==(const std::pair> &l template struct Lazy { typedef Lazy Out; - Lazy(const LazyObject *obj = nullptr) : - obj(obj) { - // empty - } + Lazy(const LazyObject *obj = nullptr) : obj(obj) {} operator const T *() const { return obj->ToPtr(); @@ -785,8 +737,9 @@ inline void GenericConvert(ListOf &a, const std::shared_ptr stream); @@ -873,7 +826,7 @@ public: if (it != objects_bytype.end() && (*it).second.size()) { return *(*it).second.begin(); } - return NULL; + return nullptr; } // same, but raise an exception if the object doesn't exist and return a reference @@ -965,7 +918,6 @@ private: #endif // _MSC_VER } // namespace STEP - } // namespace Assimp #endif // INCLUDED_AI_STEPFILE_H diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index d2f413932..da7591d52 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -683,7 +683,7 @@ bool glTF2Exporter::GetMatSheen(const aiMaterial &mat, glTF2::MaterialSheen &she } // Default Sheen color factor {0,0,0} disables Sheen, so do not export - if (sheen.sheenColorFactor == defaultSheenFactor) { + if (sheen.sheenColorFactor[0] == defaultSheenFactor[0] && sheen.sheenColorFactor[1] == defaultSheenFactor[1] && sheen.sheenColorFactor[2] == defaultSheenFactor[2]) { return false; } diff --git a/code/Common/DefaultIOStream.cpp b/code/Common/DefaultIOStream.cpp index 17fc44f9a..f2c772187 100644 --- a/code/Common/DefaultIOStream.cpp +++ b/code/Common/DefaultIOStream.cpp @@ -63,7 +63,7 @@ inline int select_fseek(FILE *file, int64_t offset, int origin) { -#if defined _WIN64 && (!defined __GNUC__ || __MSVCRT_VERSION__ >= 0x0601) +#if defined _WIN32 && (!defined __GNUC__ || !defined __CLANG__ && __MSVCRT_VERSION__ >= 0x0601) template <> inline size_t select_ftell<8>(FILE *file) { return (size_t)::_ftelli64(file); @@ -74,7 +74,7 @@ inline int select_fseek<8>(FILE *file, int64_t offset, int origin) { return ::_fseeki64(file, offset, origin); } -#endif // #if defined _WIN32 && (!defined __GNUC__ || __MSVCRT_VERSION__ >= 0x0601) +#endif } // namespace @@ -149,13 +149,20 @@ size_t DefaultIOStream::FileSize() const { // // See here for details: // https://www.securecoding.cert.org/confluence/display/seccode/FIO19-C.+Do+not+use+fseek()+and+ftell()+to+compute+the+size+of+a+regular+file -#if defined _WIN64 && (!defined __GNUC__ || __MSVCRT_VERSION__ >= 0x0601) +#if defined _WIN32 && (!defined __GNUC__ || !defined __CLANG__ && __MSVCRT_VERSION__ >= 0x0601) struct __stat64 fileStat; //using fileno + fstat avoids having to handle the filename int err = _fstat64(_fileno(mFile), &fileStat); if (0 != err) return 0; mCachedSize = (size_t)(fileStat.st_size); +#elif defined _WIN32 + struct _stat32 fileStat; + //using fileno + fstat avoids having to handle the filename + int err = _fstat32(_fileno(mFile), &fileStat); + if (0 != err) + return 0; + mCachedSize = (size_t)(fileStat.st_size); #elif defined __GNUC__ || defined __APPLE__ || defined __MACH__ || defined __FreeBSD__ struct stat fileStat; int err = stat(mFilename.c_str(), &fileStat); diff --git a/code/Common/ScenePreprocessor.cpp b/code/Common/ScenePreprocessor.cpp index 2ef291eeb..60133f651 100644 --- a/code/Common/ScenePreprocessor.cpp +++ b/code/Common/ScenePreprocessor.cpp @@ -105,36 +105,39 @@ void ScenePreprocessor::ProcessMesh(aiMesh *mesh) { for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { if (!mesh->mTextureCoords[i]) { mesh->mNumUVComponents[i] = 0; - } else { - if (!mesh->mNumUVComponents[i]) { - mesh->mNumUVComponents[i] = 2; + continue; + } + + if (!mesh->mNumUVComponents[i]) { + mesh->mNumUVComponents[i] = 2; + } + + aiVector3D *p = mesh->mTextureCoords[i], *end = p + mesh->mNumVertices; + + // Ensure unused components are zeroed. This will make 1D texture channels work + // as if they were 2D channels .. just in case an application doesn't handle + // this case + if (2 == mesh->mNumUVComponents[i]) { + size_t num = 0; + for (; p != end; ++p) { + p->z = 0.f; + num++; } - - aiVector3D *p = mesh->mTextureCoords[i], *end = p + mesh->mNumVertices; - - // Ensure unused components are zeroed. This will make 1D texture channels work - // as if they were 2D channels .. just in case an application doesn't handle - // this case - if (2 == mesh->mNumUVComponents[i]) { - for (; p != end; ++p) { - p->z = 0.f; - } - } else if (1 == mesh->mNumUVComponents[i]) { - for (; p != end; ++p) { - p->z = p->y = 0.f; - } - } else if (3 == mesh->mNumUVComponents[i]) { - // Really 3D coordinates? Check whether the third coordinate is != 0 for at least one element - for (; p != end; ++p) { - if (p->z != 0) { - break; - } - } - if (p == end) { - ASSIMP_LOG_WARN("ScenePreprocessor: UVs are declared to be 3D but they're obviously not. Reverting to 2D."); - mesh->mNumUVComponents[i] = 2; + } else if (1 == mesh->mNumUVComponents[i]) { + for (; p != end; ++p) { + p->z = p->y = 0.f; + } + } else if (3 == mesh->mNumUVComponents[i]) { + // Really 3D coordinates? Check whether the third coordinate is != 0 for at least one element + for (; p != end; ++p) { + if (p->z != 0) { + break; } } + if (p == end) { + ASSIMP_LOG_WARN("ScenePreprocessor: UVs are declared to be 3D but they're obviously not. Reverting to 2D."); + mesh->mNumUVComponents[i] = 2; + } } } diff --git a/code/Common/ZipArchiveIOSystem.cpp b/code/Common/ZipArchiveIOSystem.cpp index e0c9883d2..a29380838 100644 --- a/code/Common/ZipArchiveIOSystem.cpp +++ b/code/Common/ZipArchiveIOSystem.cpp @@ -196,7 +196,9 @@ zlib_filefunc_def IOSystem2Unzip::get(IOSystem *pIOHandler) { zlib_filefunc_def mapping; mapping.zopen_file = (open_file_func)open; +#ifdef _UNZ_H mapping.zopendisk_file = (opendisk_file_func)opendisk; +#endif mapping.zread_file = (read_file_func)read; mapping.zwrite_file = (write_file_func)write; mapping.ztell_file = (tell_file_func)tell; diff --git a/code/PostProcessing/EmbedTexturesProcess.cpp b/code/PostProcessing/EmbedTexturesProcess.cpp index 2f80c908e..7ac4ddd4e 100644 --- a/code/PostProcessing/EmbedTexturesProcess.cpp +++ b/code/PostProcessing/EmbedTexturesProcess.cpp @@ -128,7 +128,7 @@ bool EmbedTexturesProcess::addTexture(aiScene *pScene, const std::string &path) aiTexel* imageContent = new aiTexel[ 1ul + static_cast( imageSize ) / sizeof(aiTexel)]; pFile->Seek(0, aiOrigin_SET); - pFile->Read(reinterpret_cast(imageContent), imageSize, 1); + pFile->Read(reinterpret_cast(imageContent), static_cast(imageSize), 1); mIOHandler->Close(pFile); // Enlarging the textures table diff --git a/code/res/assimp.rc b/code/res/assimp.rc index c36d812f8..fd10935f6 100644 --- a/code/res/assimp.rc +++ b/code/res/assimp.rc @@ -1,5 +1,9 @@ #include "revision.h" +#ifdef __GNUC__ +#include "winresrc.h" +#else #include "winres.h" +#endif LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL #pragma code_page(1252) diff --git a/contrib/stb/stb_image.h b/contrib/stb/stb_image.h index 65a205f6e..8d173c66a 100644 --- a/contrib/stb/stb_image.h +++ b/contrib/stb/stb_image.h @@ -4941,7 +4941,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) { stbi_uc palette[1024], pal_img_n=0; stbi_uc has_trans=0, tc[3]={0}; - stbi__uint16 tc16[3]; + stbi__uint16 tc16[3]={0}; stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; int first=1,k,interlace=0, color=0, is_iphone=0; stbi__context *s = z->s; diff --git a/include/assimp/XmlParser.h b/include/assimp/XmlParser.h index 28f2be8e8..a625f82fb 100644 --- a/include/assimp/XmlParser.h +++ b/include/assimp/XmlParser.h @@ -99,295 +99,129 @@ template class TXmlParser { public: /// @brief The default class constructor. - TXmlParser() : - mDoc(nullptr), - mData() { - // empty - } + TXmlParser(); /// @brief The class destructor. - ~TXmlParser() { - clear(); - } + ~TXmlParser(); /// @brief Will clear the parsed xml-file. - void clear() { - if (mData.empty()) { - mDoc = nullptr; - return; - } - mData.clear(); - delete mDoc; - mDoc = nullptr; - } + void clear(); /// @brief Will search for a child-node by its name /// @param name [in] The name of the child-node. /// @return The node instance or nullptr, if nothing was found. - TNodeType *findNode(const std::string &name) { - if (name.empty()) { - return nullptr; - } - - if (nullptr == mDoc) { - return nullptr; - } - - find_node_by_name_predicate predicate(name); - mCurrent = mDoc->find_node(predicate); - if (mCurrent.empty()) { - return nullptr; - } - - return &mCurrent; - } + TNodeType *findNode(const std::string &name); /// @brief Will return true, if the node is a child-node. /// @param name [in] The name of the child node to look for. /// @return true, if the node is a child-node or false if not. - bool hasNode(const std::string &name) { - return nullptr != findNode(name); - } + bool hasNode(const std::string &name); /// @brief Will parse an xml-file from a given stream. /// @param stream The input stream. /// @return true, if the parsing was successful, false if not. - bool parse(IOStream *stream) { - if (nullptr == stream) { - ASSIMP_LOG_DEBUG("Stream is nullptr."); - return false; - } + bool parse(IOStream *stream); - const size_t len = stream->FileSize(); - mData.resize(len + 1); - memset(&mData[0], '\0', len + 1); - stream->Read(&mData[0], 1, len); - - mDoc = new pugi::xml_document(); - pugi::xml_parse_result parse_result = mDoc->load_string(&mData[0], pugi::parse_full); - if (parse_result.status == pugi::status_ok) { - return true; - } - - ASSIMP_LOG_DEBUG("Error while parse xml.", std::string(parse_result.description()), " @ ", parse_result.offset); - - return false; - } - - /// @brief Will return truem if a root node is there. + /// @brief Will return true if a root node is there. /// @return true in case of an existing root. - bool hasRoot() const { - return nullptr != mDoc; - } + bool hasRoot() const; + /// @brief Will return the document pointer, is nullptr if no xml-file was parsed. /// @return The pointer showing to the document. - pugi::xml_document *getDocument() const { - return mDoc; - } + pugi::xml_document *getDocument() const; /// @brief Will return the root node, const version. /// @return The root node. - const TNodeType getRootNode() const { - static pugi::xml_node none; - if (nullptr == mDoc) { - return none; - } - return mDoc->root(); - } + const TNodeType getRootNode() const; /// @brief Will return the root node, non-const version. /// @return The root node. - TNodeType getRootNode() { - static pugi::xml_node none; - if (nullptr == mDoc) { - return none; - } - return mDoc->root(); - } + TNodeType getRootNode(); /// @brief Will check if a node with the given name is in. /// @param node [in] The node to look in. /// @param name [in] The name of the child-node. /// @return true, if node was found, false if not. - static inline bool hasNode(XmlNode &node, const char *name) { - pugi::xml_node child = node.find_child(find_node_by_name_predicate(name)); - return !child.empty(); - } + static inline bool hasNode(XmlNode &node, const char *name); /// @brief Will check if an attribute is part of the XmlNode. /// @param xmlNode [in] The node to search in. /// @param name [in} The attribute name to look for. /// @return true, if the was found, false if not. - static inline bool hasAttribute(XmlNode &xmlNode, const char *name) { - pugi::xml_attribute attr = xmlNode.attribute(name); - return !attr.empty(); - } + static inline bool hasAttribute(XmlNode &xmlNode, const char *name); /// @brief Will try to get an unsigned int attribute value. /// @param xmlNode [in] The node to search in. /// @param name [in] The attribute name to look for. /// @param val [out] The unsigned int value from the attribute. /// @return true, if the node contains an attribute with the given name and if the value is an unsigned int. - static inline bool getUIntAttribute(XmlNode &xmlNode, const char *name, unsigned int &val) { - pugi::xml_attribute attr = xmlNode.attribute(name); - if (attr.empty()) { - return false; - } - - val = attr.as_uint(); - return true; - } + static inline bool getUIntAttribute(XmlNode &xmlNode, const char *name, unsigned int &val); /// @brief Will try to get an int attribute value. /// @param xmlNode [in] The node to search in. /// @param name [in] The attribute name to look for. /// @param val [out] The int value from the attribute. /// @return true, if the node contains an attribute with the given name and if the value is an int. - static inline bool getIntAttribute(XmlNode &xmlNode, const char *name, int &val) { - pugi::xml_attribute attr = xmlNode.attribute(name); - if (attr.empty()) { - return false; - } - - val = attr.as_int(); - return true; - } + static inline bool getIntAttribute(XmlNode &xmlNode, const char *name, int &val); /// @brief Will try to get a real attribute value. /// @param xmlNode [in] The node to search in. /// @param name [in] The attribute name to look for. /// @param val [out] The real value from the attribute. /// @return true, if the node contains an attribute with the given name and if the value is a real. - static inline bool getRealAttribute(XmlNode &xmlNode, const char *name, ai_real &val) { - pugi::xml_attribute attr = xmlNode.attribute(name); - if (attr.empty()) { - return false; - } -#ifdef ASSIMP_DOUBLE_PRECISION - val = attr.as_double(); -#else - val = attr.as_float(); -#endif - return true; - } + static inline bool getRealAttribute(XmlNode &xmlNode, const char *name, ai_real &val); /// @brief Will try to get a float attribute value. /// @param xmlNode [in] The node to search in. /// @param name [in] The attribute name to look for. /// @param val [out] The float value from the attribute. /// @return true, if the node contains an attribute with the given name and if the value is a float. - static inline bool getFloatAttribute(XmlNode &xmlNode, const char *name, float &val) { - pugi::xml_attribute attr = xmlNode.attribute(name); - if (attr.empty()) { - return false; - } - - val = attr.as_float(); - return true; - } + static inline bool getFloatAttribute(XmlNode &xmlNode, const char *name, float &val); /// @brief Will try to get a double attribute value. /// @param xmlNode [in] The node to search in. /// @param name [in] The attribute name to look for. /// @param val [out] The double value from the attribute. /// @return true, if the node contains an attribute with the given name and if the value is a double. - static inline bool getDoubleAttribute(XmlNode &xmlNode, const char *name, double &val) { - pugi::xml_attribute attr = xmlNode.attribute(name); - if (attr.empty()) { - return false; - } - - val = attr.as_double(); - return true; - } + static inline bool getDoubleAttribute(XmlNode &xmlNode, const char *name, double &val); /// @brief Will try to get a std::string attribute value. /// @param xmlNode [in] The node to search in. /// @param name [in] The attribute name to look for. /// @param val [out] The std::string value from the attribute. /// @return true, if the node contains an attribute with the given name and if the value is a std::string. - static inline bool getStdStrAttribute(XmlNode &xmlNode, const char *name, std::string &val) { - pugi::xml_attribute attr = xmlNode.attribute(name); - if (attr.empty()) { - return false; - } - - val = attr.as_string(); - return true; - } + static inline bool getStdStrAttribute(XmlNode &xmlNode, const char *name, std::string &val); /// @brief Will try to get a bool attribute value. /// @param xmlNode [in] The node to search in. /// @param name [in] The attribute name to look for. /// @param val [out] The bool value from the attribute. /// @return true, if the node contains an attribute with the given name and if the value is a bool. - static inline bool getBoolAttribute(XmlNode &xmlNode, const char *name, bool &val) { - pugi::xml_attribute attr = xmlNode.attribute(name); - if (attr.empty()) { - return false; - } - - val = attr.as_bool(); - return true; - } + static inline bool getBoolAttribute(XmlNode &xmlNode, const char *name, bool &val); /// @brief Will try to get the value of the node as a string. /// @param node [in] The node to search in. /// @param text [out] The value as a text. /// @return true, if the value can be read out. - static inline bool getValueAsString(XmlNode &node, std::string &text) { - text = std::string(); - if (node.empty()) { - return false; - } - - text = node.text().as_string(); - - return true; - } + static inline bool getValueAsString(XmlNode &node, std::string &text); /// @brief Will try to get the value of the node as a float. /// @param node [in] The node to search in. /// @param text [out] The value as a float. /// @return true, if the value can be read out. - static inline bool getValueAsFloat(XmlNode &node, ai_real &v) { - if (node.empty()) { - return false; - } - - v = node.text().as_float(); - - return true; - } + static inline bool getValueAsFloat(XmlNode &node, ai_real &v); /// @brief Will try to get the value of the node as an integer. /// @param node [in] The node to search in. /// @param text [out] The value as a int. /// @return true, if the value can be read out. - static inline bool getValueAsInt(XmlNode &node, int &v) { - if (node.empty()) { - return false; - } - - v = node.text().as_int(); - - return true; - } + static inline bool getValueAsInt(XmlNode &node, int &v); /// @brief Will try to get the value of the node as an bool. /// @param node [in] The node to search in. /// @param text [out] The value as a bool. /// @return true, if the value can be read out. - static inline bool getValueAsBool(XmlNode& node, bool& v) - { - if (node.empty()) { - return false; - } - - v = node.text().as_bool(); - - return true; - } + static inline bool getValueAsBool(XmlNode &node, bool &v); private: pugi::xml_document *mDoc; @@ -395,6 +229,254 @@ private: std::vector mData; }; +template +inline TXmlParser::TXmlParser() : + mDoc(nullptr), + mData() { + // empty +} + +template +inline TXmlParser::~TXmlParser() { + clear(); +} + +template +inline void TXmlParser::clear() { + if (mData.empty()) { + if (mDoc) { + delete mDoc; + } + mDoc = nullptr; + return; + } + + mData.clear(); + delete mDoc; + mDoc = nullptr; +} + +template +inline TNodeType *TXmlParser::findNode(const std::string &name) { + if (name.empty()) { + return nullptr; + } + + if (nullptr == mDoc) { + return nullptr; + } + + find_node_by_name_predicate predicate(name); + mCurrent = mDoc->find_node(predicate); + if (mCurrent.empty()) { + return nullptr; + } + + return &mCurrent; +} + +template +bool TXmlParser::hasNode(const std::string &name) { + return nullptr != findNode(name); +} + +template +bool TXmlParser::parse(IOStream *stream) { + if (hasRoot()) { + clear(); + } + + if (nullptr == stream) { + ASSIMP_LOG_DEBUG("Stream is nullptr."); + return false; + } + + const size_t len = stream->FileSize(); + mData.resize(len + 1); + memset(&mData[0], '\0', len + 1); + stream->Read(&mData[0], 1, len); + + mDoc = new pugi::xml_document(); + pugi::xml_parse_result parse_result = mDoc->load_string(&mData[0], pugi::parse_full); + if (parse_result.status == pugi::status_ok) { + return true; + } + + ASSIMP_LOG_DEBUG("Error while parse xml.", std::string(parse_result.description()), " @ ", parse_result.offset); + + return false; +} + +template +bool TXmlParser::hasRoot() const { + return nullptr != mDoc; +} + +template +pugi::xml_document *TXmlParser::getDocument() const { + return mDoc; +} + +template +const TNodeType TXmlParser::getRootNode() const { + static pugi::xml_node none; + if (nullptr == mDoc) { + return none; + } + return mDoc->root(); +} + +template +TNodeType TXmlParser::getRootNode() { + static pugi::xml_node none; + if (nullptr == mDoc) { + return none; + } + + return mDoc->root(); +} + +template +inline bool TXmlParser::hasNode(XmlNode &node, const char *name) { + pugi::xml_node child = node.find_child(find_node_by_name_predicate(name)); + return !child.empty(); +} + +template +inline bool TXmlParser::hasAttribute(XmlNode &xmlNode, const char *name) { + pugi::xml_attribute attr = xmlNode.attribute(name); + return !attr.empty(); +} + +template +inline bool TXmlParser::getUIntAttribute(XmlNode &xmlNode, const char *name, unsigned int &val) { + pugi::xml_attribute attr = xmlNode.attribute(name); + if (attr.empty()) { + return false; + } + + val = attr.as_uint(); + return true; +} + +template +inline bool TXmlParser::getIntAttribute(XmlNode &xmlNode, const char *name, int &val) { + pugi::xml_attribute attr = xmlNode.attribute(name); + if (attr.empty()) { + return false; + } + + val = attr.as_int(); + return true; +} + +template +inline bool TXmlParser::getRealAttribute(XmlNode &xmlNode, const char *name, ai_real &val) { + pugi::xml_attribute attr = xmlNode.attribute(name); + if (attr.empty()) { + return false; + } +#ifdef ASSIMP_DOUBLE_PRECISION + val = attr.as_double(); +#else + val = attr.as_float(); +#endif + return true; +} + +template +inline bool TXmlParser::getFloatAttribute(XmlNode &xmlNode, const char *name, float &val) { + pugi::xml_attribute attr = xmlNode.attribute(name); + if (attr.empty()) { + return false; + } + + val = attr.as_float(); + + return true; +} + +template +inline bool TXmlParser::getDoubleAttribute(XmlNode &xmlNode, const char *name, double &val) { + pugi::xml_attribute attr = xmlNode.attribute(name); + if (attr.empty()) { + return false; + } + + val = attr.as_double(); + + return true; +} + +template +inline bool TXmlParser::getStdStrAttribute(XmlNode &xmlNode, const char *name, std::string &val) { + pugi::xml_attribute attr = xmlNode.attribute(name); + if (attr.empty()) { + return false; + } + + val = attr.as_string(); + + return true; +} + +template +inline bool TXmlParser::getBoolAttribute(XmlNode &xmlNode, const char *name, bool &val) { + pugi::xml_attribute attr = xmlNode.attribute(name); + if (attr.empty()) { + return false; + } + + val = attr.as_bool(); + + return true; +} + +template +inline bool TXmlParser::getValueAsString(XmlNode &node, std::string &text) { + text = std::string(); + if (node.empty()) { + return false; + } + + text = node.text().as_string(); + + return true; +} + +template +inline bool TXmlParser::getValueAsFloat(XmlNode &node, ai_real &v) { + if (node.empty()) { + return false; + } + + v = node.text().as_float(); + + return true; +} + +template +inline bool TXmlParser::getValueAsInt(XmlNode &node, int &v) { + if (node.empty()) { + return false; + } + + v = node.text().as_int(); + + return true; +} + +template +inline bool TXmlParser::getValueAsBool(XmlNode &node, bool &v) { + if (node.empty()) { + return false; + } + + v = node.text().as_bool(); + + return true; +} + using XmlParser = TXmlParser; /// @brief This class declares an iterator to loop through all children of the root node. @@ -419,10 +501,8 @@ public: } } - /// @brief The class destructor. - ~XmlNodeIterator() { - // empty - } + /// @brief The class destructor, default implementation. + ~XmlNodeIterator() = default; /// @brief Will iterate through all children in pre-order iteration. /// @param node [in] The nod to iterate through. diff --git a/test/models/Collada/box_nested_animation.dae b/test/models/Collada/box_nested_animation.dae new file mode 100644 index 000000000..f50113b8f --- /dev/null +++ b/test/models/Collada/box_nested_animation.dae @@ -0,0 +1,196 @@ + + + + + Blender User + Blender 2.80.40 commit date:2019-01-07, commit time:23:37, hash:91a155833e59 + + 2019-01-08T17:44:11 + 2019-01-08T17:44:11 + + Z_UP + + + + + + + + 0.8 0.8 0.8 1 + + + 0 0.5 0 1 + + + + + + + + + + + + + + + + + 1 1 1 1 1 -1 1 -1 1 1 -1 -1 -1 1 1 -1 1 -1 -1 -1 1 -1 -1 -1 + + + + + + + + + + 0 0 1 0 -1 0 -1 0 0 0 0 -1 1 0 0 0 1 0 + + + + + + + + + + 0.625 0 0.375 0.25 0.375 0 0.625 0.25 0.375 0.5 0.375 0.25 0.625 0.5 0.375 0.75 0.375 0.5 0.625 0.75 0.375 1 0.375 0.75 0.375 0.5 0.125 0.75 0.125 0.5 0.875 0.5 0.625 0.75 0.625 0.5 0.625 0 0.625 0.25 0.375 0.25 0.625 0.25 0.625 0.5 0.375 0.5 0.625 0.5 0.625 0.75 0.375 0.75 0.625 0.75 0.625 1 0.375 1 0.375 0.5 0.375 0.75 0.125 0.75 0.875 0.5 0.875 0.75 0.625 0.75 + + + + + + + + + + + + + + + 3 3 3 3 3 3 3 3 3 3 3 3 +

4 0 0 2 0 1 0 0 2 2 1 3 7 1 4 3 1 5 6 2 6 5 2 7 7 2 8 1 3 9 7 3 10 5 3 11 0 4 12 3 4 13 1 4 14 4 5 15 1 5 16 5 5 17 4 0 18 6 0 19 2 0 20 2 1 21 6 1 22 7 1 23 6 2 24 4 2 25 5 2 26 1 3 27 3 3 28 7 3 29 0 4 30 2 4 31 3 4 32 4 5 33 0 5 34 1 5 35

+
+
+
+
+ + + + 1 0 0 -1 0 1 0 1 0 0 1 1 0 0 0 1 + + Bone + + + + + + + + 0.7886752 0.2113248 0.5773504 -0.5773504 -0.5773503 0.5773503 0.5773503 1.154701 -0.2113249 -0.7886752 0.5773503 -0.5773502 0 0 0 1 + + + + + + + + 1 1 1 1 1 1 1 1 + + + + + + + + + + + + + + 1 1 1 1 1 1 1 1 + 0 0 0 1 0 2 0 3 0 4 0 5 0 6 0 7 + + + + + + + + + 0.04166662 0.08333331 0.125 0.1666666 0.2083333 0.25 0.2916666 0.3333333 0.375 0.4166666 0.4583333 0.5 0.5416667 0.5833333 0.625 0.6666667 0.7083333 0.75 0.7916667 0.8333333 0.875 0.9166667 0.9583333 1 1.041667 1.083333 1.125 1.166667 1.208333 1.25 1.291667 1.333333 1.375 1.416667 1.458333 1.5 1.541667 1.583333 1.625 1.666667 + + + + + + + + 1 0 0 1 0 1 0 -1 0 0 1 0 0 0 0 1 0.9999878 3.10816e-5 0.004935208 1 0 0.9999802 -0.006297799 -1 -0.004935306 0.006297722 0.999968 0 0 0 0 1 0.999819 4.61727e-4 0.01901668 1 0 0.9997054 -0.02427293 -1 -0.01902229 0.02426853 0.9995245 0 0 0 0 1 0.9991519 0.002163141 0.04111904 1 0 0.9986191 -0.05253414 -1 -0.04117589 0.05248959 0.9977722 0 0 0 0 1 0.9975264 0.006301912 0.07000974 1 0 0.9959731 -0.08965231 -1 -0.0702928 0.08943056 0.9935095 0 0 0 0 1 0.9944467 0.01411698 0.1042901 1 0 0.9909625 -0.1341392 -1 -0.1052413 0.1333943 0.9854594 0 0 0 0 1 0.9894527 0.02671701 0.1423712 1 0 0.9828442 -0.184438 -1 -0.1448563 0.1824927 0.9724778 0 0 0 0 1 0.9821799 0.04490547 0.1825 1 0 0.9710366 -0.2389307 -1 -0.1879434 0.234673 0.9537326 0 0 0 0 1 0.9724072 0.06904543 0.2228386 1 0 0.9551992 -0.2959637 -1 -0.2332902 0.2877972 0.9288425 0 0 0 0 1 0.9600915 0.09897761 0.261587 1 0 0.9352878 -0.3538882 -1 -0.2796861 0.339765 0.8979618 0 0 0 0 1 0.9453882 0.1340003 0.2971281 1 0 0.9115852 -0.4111113 -1 -0.3259466 0.3886598 0.8618018 0 0 0 0 1 0.9286572 0.1729132 0.328172 1 0 0.8847058 -0.4661497 -1 -0.3709391 0.4328933 0.8215885 0 0 0 0 1 0.9104556 0.2141147 0.3538722 1 0 0.8555763 -0.5176768 -1 -0.4136069 0.4713217 0.7789642 0 0 0 0 1 0.8915175 0.2557371 0.3738919 1 0 0.8253933 -0.5645581 -1 -0.4529863 0.5033134 0.7358525 0 0 0 0 1 0.8727233 0.2957927 0.388408 1 0 0.7955672 -0.6058654 -1 -0.4882152 0.5287529 0.6943099 0 0 0 0 1 0.8550603 0.332307 0.3980502 1 0 0.7676533 -0.6408653 -1 -0.5185286 0.5479785 0.6563899 0 0 0 0 1 0.8395769 0.3634188 0.4037789 1 0 0.7432778 -0.6689829 -1 -0.5432408 0.5616626 0.6240388 0 0 0 0 1 0.8273312 0.3874339 0.4067161 1 0 0.7240622 -0.6897347 -1 -0.5617144 0.5706391 0.5990393 0 0 0 0 1 0.8193359 0.4028329 0.4079393 1 0 0.7115462 -0.7026393 -1 -0.5733138 0.5756976 0.5829953 0 0 0 0 1 0.8164964 0.4082482 0.4082486 1 7.75722e-8 0.707107 -0.7071065 -1 -0.5773504 0.57735 0.5773503 0 0 0 0 1 0.8190646 0.4033515 0.4079717 1 7.78161e-8 0.7111219 -0.7030687 -1 -0.5737014 0.5758587 0.5824547 0 0 0 0 1 0.8263245 0.3893851 0.4068995 1 7.85059e-8 0.7224849 -0.6913868 -1 -0.5631944 0.5713098 0.5970069 0 0 0 0 1 0.8375081 0.3675125 0.4043696 1 7.95684e-8 0.7400277 -0.6725764 -1 -0.5464249 0.5632883 0.6197791 0 0 0 0 1 0.8517552 0.3390183 0.3994742 1 8.0922e-8 0.7624427 -0.6470557 -1 -0.5239399 0.5511332 0.6494145 0 0 0 0 1 0.8681612 0.3053284 0.3912425 1 8.24806e-8 0.7883466 -0.6152314 -1 -0.4962822 0.5341201 0.6844119 0 0 0 0 1 0.8858209 0.2680094 0.3788038 1 8.41584e-8 0.8163394 -0.5775725 -1 -0.4640273 0.5116258 0.7231305 0 0 0 0 1 0.9038687 0.2287352 0.3615268 1 8.58731e-8 0.8450637 -0.5346656 -1 -0.42781 0.4832675 0.7638266 0 0 0 0 1 0.9215156 0.1892192 0.339124 1 8.75496e-8 0.8732626 -0.4872499 -1 -0.3883413 0.4490085 0.8047251 0 0 0 0 1 0.9380813 0.1511175 0.3117163 1 8.91235e-8 0.899834 -0.4362323 -1 -0.3464153 0.4092214 0.8441175 0 0 0 0 1 0.9530206 0.1159168 0.2798482 1 9.05428e-8 0.9238796 -0.3826832 -1 -0.3029055 0.3647051 0.8804763 0 0 0 0 1 0.965943 0.08482374 0.2444564 1 9.17705e-8 0.9447417 -0.3278156 -1 -0.2587547 0.3166512 0.9125667 0 0 0 0 1 0.9766233 0.05867312 0.2067956 1 9.27852e-8 0.9620277 -0.2729518 -1 -0.2149581 0.2665711 0.9395387 0 0 0 0 1 0.9850019 0.03787052 0.1683363 1 9.35812e-8 0.975616 -0.2194843 -1 -0.1725436 0.2161924 0.9609836 0 0 0 0 1 0.991176 0.02237916 0.1306496 1 9.41678e-8 0.9856446 -0.1688333 -1 -0.1325524 0.1673435 0.9769473 0 0 0 0 1 0.9953793 0.01175384 0.09529842 1 9.45671e-8 0.9924796 -0.1224106 -1 -0.09602053 0.121845 0.9878936 0 0 0 0 1 0.997952 0.005218936 0.06375288 1 9.48115e-8 0.996666 -0.08159051 -1 -0.06396614 0.08142342 0.9946249 0 0 0 0 1 0.9993011 0.001782816 0.03733916 1 9.49397e-8 0.998862 -0.04769476 -1 -0.0373817 0.04766143 0.9981638 0 0 0 0 1 0.9998515 3.78837e-4 0.01722835 1 9.4992e-8 0.9997582 -0.02198936 -1 -0.01723252 0.0219861 0.9996098 0 0 0 0 1 0.99999 2.53135e-5 0.004462156 1 9.50052e-8 0.9999838 -0.00569412 -1 -0.004462227 0.005694063 0.9999738 0 0 0 0 1 1 0 0 2 0 1 0 -1 0 0 1 0 0 0 0 1 + + + + + + + + LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR + + + + + + + + + + + + + + + + + + + 1 0 0 1 0 1 0 -1 0 0 1 0 0 0 0 1 + + 0.7886751 -0.5773503 -0.211325 0 0.2113248 0.5773503 -0.7886751 0 0.5773503 0.5773503 0.5773502 0 0 0 0 1 + + + 0 + -0.5235989 + -2 + 2 + 2 + + + + + 0 0 0 + 0 0 1 0 + 0 1 0 0 + 1 0 0 0 + 1 1 1 + + #Armature_Bone + + + + + + + + + + + + + + + +
diff --git a/test/unit/utColladaImportExport.cpp b/test/unit/utColladaImportExport.cpp index b58fa03fa..e2842732e 100644 --- a/test/unit/utColladaImportExport.cpp +++ b/test/unit/utColladaImportExport.cpp @@ -69,31 +69,44 @@ public: virtual bool importerTest() final { Assimp::Importer importer; - const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/duck.dae", aiProcess_ValidateDataStructure); - if (scene == nullptr) - return false; + { + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/duck.dae", aiProcess_ValidateDataStructure); + if (scene == nullptr) + return false; - // Expected number of items - EXPECT_EQ(scene->mNumMeshes, 1u); - EXPECT_EQ(scene->mNumMaterials, 1u); - EXPECT_EQ(scene->mNumAnimations, 0u); - EXPECT_EQ(scene->mNumTextures, 0u); - EXPECT_EQ(scene->mNumLights, 1u); - EXPECT_EQ(scene->mNumCameras, 1u); + // Expected number of items + EXPECT_EQ(scene->mNumMeshes, 1u); + EXPECT_EQ(scene->mNumMaterials, 1u); + EXPECT_EQ(scene->mNumAnimations, 0u); + EXPECT_EQ(scene->mNumTextures, 0u); + EXPECT_EQ(scene->mNumLights, 1u); + EXPECT_EQ(scene->mNumCameras, 1u); - // Expected common metadata - aiString value; - EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT, value)) << "No importer format metadata"; - EXPECT_STREQ("Collada Importer", value.C_Str()); + // Expected common metadata + aiString value; + EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT, value)) << "No importer format metadata"; + EXPECT_STREQ("Collada Importer", value.C_Str()); - EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT_VERSION, value)) << "No format version metadata"; - EXPECT_STREQ("1.4.1", value.C_Str()); + EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT_VERSION, value)) << "No format version metadata"; + EXPECT_STREQ("1.4.1", value.C_Str()); - EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_GENERATOR, value)) << "No generator metadata"; - EXPECT_EQ(strncmp(value.C_Str(), "Maya 8.0", 8), 0) << "AI_METADATA_SOURCE_GENERATOR was: " << value.C_Str(); + EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_GENERATOR, value)) << "No generator metadata"; + EXPECT_EQ(strncmp(value.C_Str(), "Maya 8.0", 8), 0) << "AI_METADATA_SOURCE_GENERATOR was: " << value.C_Str(); - EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_COPYRIGHT, value)) << "No copyright metadata"; - EXPECT_EQ(strncmp(value.C_Str(), "Copyright 2006", 14), 0) << "AI_METADATA_SOURCE_COPYRIGHT was: " << value.C_Str(); + EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_COPYRIGHT, value)) << "No copyright metadata"; + EXPECT_EQ(strncmp(value.C_Str(), "Copyright 2006", 14), 0) << "AI_METADATA_SOURCE_COPYRIGHT was: " << value.C_Str(); + } + + { + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/box_nested_animation.dae", aiProcess_ValidateDataStructure); + if (scene == nullptr) + return false; + + // Expect only one animation with the correct name + EXPECT_EQ(scene->mNumAnimations, 1u); + EXPECT_EQ(std::string(scene->mAnimations[0]->mName.C_Str()), std::string("Armature")); + + } return true; } diff --git a/test/unit/utOpenGEXImportExport.cpp b/test/unit/utOpenGEXImportExport.cpp index a7b682063..ed22a6fb7 100644 --- a/test/unit/utOpenGEXImportExport.cpp +++ b/test/unit/utOpenGEXImportExport.cpp @@ -40,6 +40,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "AbstractImportExportBase.h" + +#include #include "UnitTestPCH.h" #include @@ -51,11 +53,12 @@ public: bool importerTest() override { Assimp::Importer importer; const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/OpenGEX/Example.ogex", 0); + EXPECT_EQ(1u, scene->mNumMeshes); return nullptr != scene; } }; -TEST_F(utOpenGEXImportExport, importLWSFromFileTest) { +TEST_F(utOpenGEXImportExport, importOpenGexFromFileTest) { EXPECT_TRUE(importerTest()); }