diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 2c5ca438b..1c533aa80 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -16,7 +16,7 @@ jobs: strategy: fail-fast: false matrix: - name: [ubuntu-latest-g++, macos-latest-clang++, windows-latest-cl.exe, ubuntu-latest-clang++, ubuntu-gcc-hunter, macos-clang-hunter, windows-msvc-hunter] + name: [ubuntu-latest-g++, macos-latest-clang++, windows-latest-cl.exe, ubuntu-latest-clang++] # For Windows msvc, for Linux and macOS let's use the clang compiler, use gcc for Linux. include: - name: windows-latest-cl.exe @@ -35,15 +35,6 @@ jobs: os: ubuntu-latest cxx: g++ cc: gcc - - name: ubuntu-gcc-hunter - os: ubuntu-latest - toolchain: ninja-gcc-cxx17-fpic - - name: macos-clang-hunter - os: macos-latest - toolchain: ninja-clang-cxx17-fpic - - name: windows-msvc-hunter - os: windows-latest - toolchain: ninja-vs-win64-cxx17 steps: - uses: actions/checkout@v4 @@ -55,25 +46,11 @@ jobs: - uses: ilammy/msvc-dev-cmd@v1 - name: Set Compiler Environment - if: "!endsWith(matrix.name, 'hunter')" uses: lukka/set-shell-env@v1 with: CXX: ${{ matrix.cxx }} CC: ${{ matrix.cc }} - - name: Set Compiler Environment for Hunter on Windows - if: startsWith(matrix.name, 'windows') && endsWith(matrix.name, 'hunter') - uses: lukka/set-shell-env@v1 - with: - VS160COMNTOOLS: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools - - - name: Checkout Hunter toolchains - if: endsWith(matrix.name, 'hunter') - uses: actions/checkout@v4 - with: - repository: cpp-pm/polly - path: cmake/polly - - name: Cache DX SDK id: dxcache if: contains(matrix.name, 'windows') @@ -121,7 +98,7 @@ jobs: run: cd build/bin && ./unit ${{ steps.hunter_extra_test_args.outputs.args }} shell: bash - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 if: matrix.name == 'windows-msvc' with: name: 'assimp-bins-${{ matrix.name }}-${{ github.sha }}' diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml index a84be8cbc..38f54ce06 100644 --- a/.github/workflows/cifuzz.yml +++ b/.github/workflows/cifuzz.yml @@ -19,7 +19,7 @@ jobs: dry-run: false language: c++ - name: Upload Crash - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: failure() && steps.build.outcome == 'success' with: name: artifacts diff --git a/CMakeLists.txt b/CMakeLists.txt index 88f69174a..868282ef2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,7 +137,7 @@ IF (WIN32) ELSE() OPTION( ASSIMP_BUILD_ZLIB "Build your own zlib" - ON + OFF ) ENDIF() @@ -311,9 +311,9 @@ ELSEIF( MINGW ) SET(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}") ENDIF() IF (CMAKE_BUILD_TYPE STREQUAL "Debug") - SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long -Wa,-mbig-obj -g ${CMAKE_CXX_FLAGS}") + SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wno-dangling-reference -Wall -Wno-long-long -Wa,-mbig-obj -g ${CMAKE_CXX_FLAGS}") ELSE() - SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long -Wa,-mbig-obj -O3 ${CMAKE_CXX_FLAGS}") + SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wno-dangling-reference -Wall -Wno-long-long -Wa,-mbig-obj -O3 ${CMAKE_CXX_FLAGS}") ENDIF() SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}") ENDIF() diff --git a/code/AssetLib/3MF/D3MFImporter.cpp b/code/AssetLib/3MF/D3MFImporter.cpp index e8529064c..9a5081db9 100644 --- a/code/AssetLib/3MF/D3MFImporter.cpp +++ b/code/AssetLib/3MF/D3MFImporter.cpp @@ -81,12 +81,17 @@ static constexpr aiImporterDesc desc = { "3mf" }; -bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool /*checkSig*/) const { +bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool ) const { if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) { return false; } - D3MF::D3MFOpcPackage opcPackage(pIOHandler, filename); - return opcPackage.validate(); + static const char *const ModelRef = "3D/3dmodel.model"; + ZipArchiveIOSystem archive(pIOHandler, filename); + if (!archive.Exists(ModelRef)) { + return false; + } + + return true; } void D3MFImporter::SetupProperties(const Importer*) { diff --git a/code/AssetLib/IFC/IFCReaderGen1_2x3.cpp b/code/AssetLib/IFC/IFCReaderGen1_2x3.cpp index 73e3c91d8..c625f1daf 100644 --- a/code/AssetLib/IFC/IFCReaderGen1_2x3.cpp +++ b/code/AssetLib/IFC/IFCReaderGen1_2x3.cpp @@ -2725,6 +2725,10 @@ template <> size_t GenericFill(const DB& db, const L do { // convert the 'CompositionType' argument std::shared_ptr arg = params[base++]; if (dynamic_cast(&*arg)) { in->ObjectHelper::aux_is_derived[1]=true; break; } + if (dynamic_cast(&*arg)) { + // Consider assigning the default value as in->CompositionType = "ELEMENT". + break; + } try { GenericConvert( in->CompositionType, arg, db ); break; } catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 8 to IfcSpatialStructureElement to be a `IfcElementCompositionEnum`")); } } while (false); diff --git a/code/AssetLib/Irr/IRRLoader.cpp b/code/AssetLib/Irr/IRRLoader.cpp index 99e053892..2a481a6d8 100644 --- a/code/AssetLib/Irr/IRRLoader.cpp +++ b/code/AssetLib/Irr/IRRLoader.cpp @@ -1234,7 +1234,10 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy // Parse the XML // Find the scene root from document root. const pugi::xml_node &sceneRoot = documentRoot.child("irr_scene"); - if (!sceneRoot) throw new DeadlyImportError("IRR: not found in file"); + if (!sceneRoot) { + delete root; + throw new DeadlyImportError("IRR: not found in file"); + } for (pugi::xml_node &child : sceneRoot.children()) { // XML elements are either nodes, animators, attributes, or materials if (!ASSIMP_stricmp(child.name(), "node")) { diff --git a/code/AssetLib/MDL/MDLMaterialLoader.cpp b/code/AssetLib/MDL/MDLMaterialLoader.cpp index 3d39fa645..f8dafdb3e 100644 --- a/code/AssetLib/MDL/MDLMaterialLoader.cpp +++ b/code/AssetLib/MDL/MDLMaterialLoader.cpp @@ -123,9 +123,8 @@ aiColor4D MDLImporter::ReplaceTextureWithColor(const aiTexture *pcTexture) { // Read a texture from a MDL3 file void MDLImporter::CreateTextureARGB8_3DGS_MDL3(const unsigned char *szData) { const MDL::Header *pcHeader = (const MDL::Header *)mBuffer; //the endianness is already corrected in the InternReadFile_3DGS_MDL345 function - - VALIDATE_FILE_SIZE(szData + pcHeader->skinwidth * - pcHeader->skinheight); + const size_t len = pcHeader->skinwidth * pcHeader->skinheight; + VALIDATE_FILE_SIZE(szData + len); // allocate a new texture object aiTexture *pcNew = new aiTexture(); diff --git a/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp b/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp index 3c56775e8..a82f29cf1 100644 --- a/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp +++ b/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp @@ -395,7 +395,10 @@ void Q3BSPFileImporter::createTriangleTopology(const Q3BSP::Q3BSPModel *pModel, m_pCurrentFace->mIndices = new unsigned int[3]; m_pCurrentFace->mIndices[idx] = vertIdx; } - } + } else { + m_pCurrentFace->mIndices[idx] = vertIdx; + } + pMesh->mVertices[vertIdx].Set(pVertex->vPosition.x, pVertex->vPosition.y, pVertex->vPosition.z); pMesh->mNormals[vertIdx].Set(pVertex->vNormal.x, pVertex->vNormal.y, pVertex->vNormal.z); diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index 3ae40f07e..8d500b156 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -720,7 +720,7 @@ const vec4 defaultBaseColor = { 1, 1, 1, 1 }; const vec3 defaultEmissiveFactor = { 0, 0, 0 }; const vec4 defaultDiffuseFactor = { 1, 1, 1, 1 }; const vec3 defaultSpecularFactor = { 1, 1, 1 }; -const vec3 defaultSpecularColorFactor = { 0, 0, 0 }; +const vec3 defaultSpecularColorFactor = { 1, 1, 1 }; const vec3 defaultSheenFactor = { 0, 0, 0 }; const vec3 defaultAttenuationColor = { 1, 1, 1 }; diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index 5781a4be6..61964d1b4 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -1392,7 +1392,7 @@ inline void PbrSpecularGlossiness::SetDefaults() { inline void MaterialSpecular::SetDefaults() { //KHR_materials_specular properties SetVector(specularColorFactor, defaultSpecularColorFactor); - specularFactor = 0.f; + specularFactor = 1.f; } inline void MaterialSheen::SetDefaults() { diff --git a/code/AssetLib/glTF2/glTF2AssetWriter.inl b/code/AssetLib/glTF2/glTF2AssetWriter.inl index 30f2580a2..bfd9135d3 100644 --- a/code/AssetLib/glTF2/glTF2AssetWriter.inl +++ b/code/AssetLib/glTF2/glTF2AssetWriter.inl @@ -426,13 +426,14 @@ namespace glTF2 { if (specular.specularFactor != 0.0f) { WriteFloat(materialSpecular, specular.specularFactor, "specularFactor", w.mAl); - WriteTex(materialSpecular, specular.specularTexture, "specularTexture", w.mAl); } if (specular.specularColorFactor[0] != defaultSpecularColorFactor[0] && specular.specularColorFactor[1] != defaultSpecularColorFactor[1] && specular.specularColorFactor[2] != defaultSpecularColorFactor[2]) { WriteVec(materialSpecular, specular.specularColorFactor, "specularColorFactor", w.mAl); - WriteTex(materialSpecular, specular.specularColorTexture, "specularColorTexture", w.mAl); } + WriteTex(materialSpecular, specular.specularTexture, "specularTexture", w.mAl); + WriteTex(materialSpecular, specular.specularColorTexture, "specularColorTexture", w.mAl); + if (!materialSpecular.ObjectEmpty()) { exts.AddMember("KHR_materials_specular", materialSpecular, w.mAl); } diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index 18a6ae2f4..17d162466 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -730,8 +730,8 @@ bool glTF2Exporter::GetMatSpecular(const aiMaterial &mat, glTF2::MaterialSpecula } else if (colorFactorIsZero) { specular.specularColorFactor[0] = specular.specularColorFactor[1] = specular.specularColorFactor[2] = 1.0f; } - GetMatTex(mat, specular.specularColorTexture, aiTextureType_SPECULAR); - GetMatTex(mat, specular.specularTexture, aiTextureType_SPECULAR); + GetMatTex(mat, specular.specularTexture, aiTextureType_SPECULAR, 0); + GetMatTex(mat, specular.specularColorTexture, aiTextureType_SPECULAR, 1); return true; } @@ -912,6 +912,7 @@ void glTF2Exporter::ExportMaterials() { if (GetMatSpecular(mat, specular)) { mAsset->extensionsUsed.KHR_materials_specular = true; m->materialSpecular = Nullable(specular); + GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_COLOR_DIFFUSE); } MaterialSheen sheen; diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index 4bdbe39f1..e89baaf0d 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -288,8 +288,8 @@ static aiMaterial *ImportMaterial(std::vector &embeddedTexIdxs, Asset &r, M if (std::memcmp(specular.specularColorFactor, defaultSpecularColorFactor, sizeof(glTFCommon::vec3)) != 0 || specular.specularFactor != 0.0f) { SetMaterialColorProperty(r, specular.specularColorFactor, aimat, AI_MATKEY_COLOR_SPECULAR); aimat->AddProperty(&specular.specularFactor, 1, AI_MATKEY_SPECULAR_FACTOR); - SetMaterialTextureProperty(embeddedTexIdxs, r, specular.specularTexture, aimat, aiTextureType_SPECULAR); - SetMaterialTextureProperty(embeddedTexIdxs, r, specular.specularColorTexture, aimat, aiTextureType_SPECULAR); + SetMaterialTextureProperty(embeddedTexIdxs, r, specular.specularTexture, aimat, aiTextureType_SPECULAR, 0); + SetMaterialTextureProperty(embeddedTexIdxs, r, specular.specularColorTexture, aimat, aiTextureType_SPECULAR, 1); } } // pbrSpecularGlossiness diff --git a/code/Common/DefaultIOSystem.cpp b/code/Common/DefaultIOSystem.cpp index b28910c70..a72627154 100644 --- a/code/Common/DefaultIOSystem.cpp +++ b/code/Common/DefaultIOSystem.cpp @@ -99,12 +99,12 @@ bool DefaultIOSystem::Exists(const char *pFile) const { return false; } #else - FILE *file = ::fopen(pFile, "rb"); - if (!file) { + struct stat statbuf; + stat(pFile, &statbuf); + // test for a regular file + if (!S_ISREG(statbuf.st_mode)) { return false; } - - ::fclose(file); #endif return true; @@ -116,6 +116,7 @@ IOStream *DefaultIOSystem::Open(const char *strFile, const char *strMode) { ai_assert(strFile != nullptr); ai_assert(strMode != nullptr); FILE *file; + #ifdef _WIN32 std::wstring name = Utf8ToWide(strFile); if (name.empty()) { @@ -126,6 +127,7 @@ IOStream *DefaultIOSystem::Open(const char *strFile, const char *strMode) { #else file = ::fopen(strFile, strMode); #endif + if (!file) { return nullptr; } diff --git a/code/Pbrt/PbrtExporter.cpp b/code/Pbrt/PbrtExporter.cpp index 67937019f..9e4ca293d 100644 --- a/code/Pbrt/PbrtExporter.cpp +++ b/code/Pbrt/PbrtExporter.cpp @@ -89,22 +89,27 @@ using namespace Assimp; namespace Assimp { -void ExportScenePbrt ( - const char* pFile, - IOSystem* pIOSystem, - const aiScene* pScene, - const ExportProperties* /*pProperties*/ -){ +void ExportScenePbrt(const char *pFile, IOSystem *pIOSystem, const aiScene *pScene, + const ExportProperties *) { std::string path = DefaultIOSystem::absolutePath(std::string(pFile)); std::string file = DefaultIOSystem::completeBaseName(std::string(pFile)); - + path = path + file + ".pbrt"; // initialize the exporter PbrtExporter exporter(pScene, pIOSystem, path, file); } } // end of namespace Assimp -// Constructor +static void create_embedded_textures_folder(const aiScene *scene, IOSystem *pIOSystem) { + if (scene->mNumTextures > 0) { + if (!pIOSystem->Exists("textures")) { + if (!pIOSystem->CreateDirectory("textures")) { + throw DeadlyExportError("Could not create textures/ directory."); + } + } + } +} + PbrtExporter::PbrtExporter( const aiScene *pScene, IOSystem *pIOSystem, const std::string &path, const std::string &file) : @@ -127,10 +132,10 @@ PbrtExporter::PbrtExporter( 0.f, 0.f, 1.f, 0.f, // 0.f, 0.f, 0.f, 1.f // ) * mRootTransform; + // Export embedded textures. - if (mScene->mNumTextures > 0) - if (!mIOSystem->CreateDirectory("textures")) - throw DeadlyExportError("Could not create textures/ directory."); + create_embedded_textures_folder(mScene, mIOSystem); + for (unsigned int i = 0; i < mScene->mNumTextures; ++i) { aiTexture* tex = mScene->mTextures[i]; std::string fn = CleanTextureFilename(tex->mFilename, false); @@ -176,9 +181,6 @@ PbrtExporter::PbrtExporter( outfile->Write(mOutput.str().c_str(), mOutput.str().length(), 1); } -// Destructor -PbrtExporter::~PbrtExporter() = default; - void PbrtExporter::WriteMetaData() { mOutput << "#############################\n"; mOutput << "# Scene metadata:\n"; diff --git a/code/Pbrt/PbrtExporter.h b/code/Pbrt/PbrtExporter.h index c7e8180e2..a4b1a608a 100644 --- a/code/Pbrt/PbrtExporter.h +++ b/code/Pbrt/PbrtExporter.h @@ -70,15 +70,33 @@ class ExportProperties; // --------------------------------------------------------------------- /** Helper class to export a given scene to a Pbrt file. */ // --------------------------------------------------------------------- -class PbrtExporter -{ +class PbrtExporter { public: /// Constructor for a specific scene to export PbrtExporter(const aiScene *pScene, IOSystem *pIOSystem, const std::string &path, const std::string &file); /// Destructor - virtual ~PbrtExporter(); + virtual ~PbrtExporter() = default; + +private: + aiMatrix4x4 GetNodeTransform(const aiString &name) const; + static std::string TransformAsString(const aiMatrix4x4 &m); + static std::string RemoveSuffix(std::string filename); + std::string CleanTextureFilename(const aiString &f, bool rewriteExtension = true) const; + void WriteMetaData(); + void WriteWorldDefinition(); + void WriteCameras(); + void WriteCamera(int i); + void WriteLights(); + void WriteTextures(); + static bool TextureHasAlphaMask(const std::string &filename); + void WriteMaterials(); + void WriteMaterial(int i); + void WriteMesh(aiMesh *mesh); + void WriteInstanceDefinition(int i); + void WriteGeometricObjects(aiNode *node, aiMatrix4x4 parentTransform, + std::map &meshUses); private: // the scene to export @@ -96,39 +114,11 @@ private: /// Name of the file (without extension) where the scene will be exported const std::string mFile; -private: // A private set to keep track of which textures have been declared std::set mTextureSet; // Transform to apply to the root node and all root objects such as cameras, lights, etc. aiMatrix4x4 mRootTransform; - - aiMatrix4x4 GetNodeTransform(const aiString& name) const; - static std::string TransformAsString(const aiMatrix4x4& m); - - static std::string RemoveSuffix(std::string filename); - std::string CleanTextureFilename(const aiString &f, bool rewriteExtension = true) const; - - void WriteMetaData(); - - void WriteWorldDefinition(); - - void WriteCameras(); - void WriteCamera(int i); - - void WriteLights(); - - void WriteTextures(); - static bool TextureHasAlphaMask(const std::string &filename); - - void WriteMaterials(); - void WriteMaterial(int i); - - void WriteMesh(aiMesh* mesh); - - void WriteInstanceDefinition(int i); - void WriteGeometricObjects(aiNode* node, aiMatrix4x4 parentTransform, - std::map &meshUses); }; } // namespace Assimp diff --git a/contrib/poly2tri/poly2tri/sweep/sweep.cc b/contrib/poly2tri/poly2tri/sweep/sweep.cc index 565a198d8..e1f23f11b 100644 --- a/contrib/poly2tri/poly2tri/sweep/sweep.cc +++ b/contrib/poly2tri/poly2tri/sweep/sweep.cc @@ -111,6 +111,9 @@ void Sweep::EdgeEvent(SweepContext& tcx, Edge* edge, Node* node) void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point) { + if (triangle == nullptr) + return; + if (IsEdgeSideOfTriangle(*triangle, ep, eq)) { return; } diff --git a/include/assimp/IOSystem.hpp b/include/assimp/IOSystem.hpp index 30f48b81c..acb1f8eae 100644 --- a/include/assimp/IOSystem.hpp +++ b/include/assimp/IOSystem.hpp @@ -97,7 +97,7 @@ public: * Create an instance of your derived class and assign it to an * #Assimp::Importer instance by calling Importer::SetIOHandler(). */ - IOSystem() AI_NO_EXCEPT; + IOSystem() AI_NO_EXCEPT = default; // ------------------------------------------------------------------- /** @brief Virtual destructor. @@ -105,7 +105,7 @@ public: * It is safe to be called from within DLL Assimp, we're constructed * on Assimp's heap. */ - virtual ~IOSystem(); + virtual ~IOSystem() = default; // ------------------------------------------------------------------- /** @brief For backward compatibility @@ -236,12 +236,6 @@ private: std::vector m_pathStack; }; -// ---------------------------------------------------------------------------- -AI_FORCE_INLINE IOSystem::IOSystem() AI_NO_EXCEPT = default; - -// ---------------------------------------------------------------------------- -AI_FORCE_INLINE IOSystem::~IOSystem() = default; - // ---------------------------------------------------------------------------- // For compatibility, the interface of some functions taking a std::string was // changed to const char* to avoid crashes between binary incompatible STL diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index afe487411..da6a5b00b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -165,6 +165,7 @@ SET( IMPORTERS unit/ImportExport/MDL/utMDLImporter_HL1_Nodes.cpp unit/ImportExport/RAW/utRAWImportExport.cpp unit/ImportExport/Terragen/utTerragenImportExport.cpp + unit/ImportExport/Pbrt/utPbrtImportExport.cpp ) SET( MATERIAL diff --git a/test/unit/ImportExport/Pbrt/utPbrtImportExport.cpp b/test/unit/ImportExport/Pbrt/utPbrtImportExport.cpp new file mode 100644 index 000000000..c7807205a --- /dev/null +++ b/test/unit/ImportExport/Pbrt/utPbrtImportExport.cpp @@ -0,0 +1,70 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2020, 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 "AbstractImportExportBase.h" +#include "UnitTestPCH.h" +#include +#include +#include +#include + +using namespace Assimp; + +class utPbrtImportExport : public AbstractImportExportBase { +public: +#ifndef ASSIMP_BUILD_NO_EXPORT + bool exporterTest() override { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/OBJ/spider.obj", aiProcess_ValidateDataStructure); + EXPECT_NE(scene, nullptr ); + + ::Assimp::Exporter exporter; + return AI_SUCCESS == exporter.Export(scene, "pbrt", ASSIMP_TEST_MODELS_DIR "/OBJ/spider_out.pbrt"); + } +#endif +}; + +#ifndef ASSIMP_BUILD_NO_EXPORT + +TEST_F(utPbrtImportExport, exportTest_Success) { + EXPECT_TRUE(exporterTest()); +} + +#endif // ASSIMP_BUILD_NO_EXPORT