diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index e1ab13396..3f820ec7d 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1,2 @@ open_collective: assimp +patreon: assimp diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index dd84ea782..0f9a5f105 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,8 +1,8 @@ --- name: Bug report about: Create a report to help us improve -title: '' -labels: '' +title: 'Bug:' +labels: 'Bug' assignees: '' --- @@ -23,16 +23,10 @@ A clear and concise description of what you expected to happen. **Screenshots** If applicable, add screenshots to help explain your problem. -**Desktop (please complete the following information):** +**Platform (please complete the following information):** - OS: [e.g. iOS] - Browser [e.g. chrome, safari] - Version [e.g. 22] -**Smartphone (please complete the following information):** - - Device: [e.g. iPhone6] - - OS: [e.g. iOS8.1] - - Browser [e.g. stock browser, safari] - - Version [e.g. 22] - **Additional context** Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index bbcbbe7d6..87302a0f0 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -2,7 +2,7 @@ name: Feature request about: Suggest an idea for this project title: '' -labels: '' +labels: 'Feature-Request' assignees: '' --- diff --git a/.github/ISSUE_TEMPLATE/tech_debt.md b/.github/ISSUE_TEMPLATE/tech_debt.md new file mode 100644 index 000000000..a1172d932 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/tech_debt.md @@ -0,0 +1,25 @@ +--- +name: Technical debt +about: Create a report to help us to fix and detect tech debts +title: '' +labels: 'Techdebt' +assignees: '' + +--- + +**Describe the technical debt** +A clear and concise description of what the tech debt is about. + +**Better solution** +A clear and concise description of what you would expect. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.gitignore b/.gitignore index 0a999d3aa..09d631ee8 100644 --- a/.gitignore +++ b/.gitignore @@ -25,7 +25,7 @@ CMakeSettings.json # Output bin/ lib/ - +x64/ # QtCreator CMakeLists.txt.user @@ -94,6 +94,7 @@ test/gtest/src/gtest-stamp/gtest-gitinfo.txt test/gtest/src/gtest-stamp/gtest-gitclone-lastrun.txt Assimp.opensdf contrib/zlib/CTestTestfile.cmake +contrib/zlib/Debug/zlibstaticd.pdb ipch/assimp_viewer-44bbbcd1/assimp_viewerd-ccc45335.ipch bin64/assimp-vc140-mt.dll bin64/assimp-vc140-mtd.dll @@ -118,4 +119,4 @@ tools/assimp_qt_viewer/moc_mainwindow.cpp_parameters tools/assimp_qt_viewer/ui_mainwindow.h #Generated directory -generated/* \ No newline at end of file +generated/* diff --git a/CMakeLists.txt b/CMakeLists.txt index 7027e3300..4e47b5732 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,16 +44,16 @@ CMAKE_MINIMUM_REQUIRED( VERSION 3.10 ) option(ASSIMP_HUNTER_ENABLED "Enable Hunter package manager support" OFF) IF(ASSIMP_HUNTER_ENABLED) - include("cmake/HunterGate.cmake") + include("cmake-modules/HunterGate.cmake") HunterGate( - URL "https://github.com/cpp-pm/hunter/archive/v0.23.293.tar.gz" - SHA1 "e8e5470652db77149d9b38656db2a6c0b7642693" + URL "https://github.com/cpp-pm/hunter/archive/v0.23.311.tar.gz" + SHA1 "1a82b9b73055879181cb1466b2ab5d48ee8ae410" ) add_definitions(-DASSIMP_USE_HUNTER) ENDIF() -PROJECT( Assimp VERSION 5.0.1 ) +PROJECT(Assimp VERSION 5.1.0) # All supported options ############################################### @@ -135,11 +135,11 @@ IF ( WIN32 ) # Use subset of Windows.h ADD_DEFINITIONS( -DWIN32_LEAN_AND_MEAN ) - OPTION ( ASSIMP_BUILD_ASSIMP_VIEW - "If the Assimp view tool is built. (requires DirectX)" - OFF ) - IF(MSVC) + OPTION ( ASSIMP_BUILD_ASSIMP_VIEW + "If the Assimp view tool is built. (requires DirectX)" + OFF ) + OPTION( ASSIMP_INSTALL_PDB "Install MSVC debug files." ON ) @@ -265,9 +265,12 @@ ELSEIF(MSVC) ENDIF() # disable "elements of array '' will be default initialized" warning on MSVC2013 IF(MSVC12) - ADD_COMPILE_OPTIONS(/wd4351) + ADD_COMPILE_OPTIONS(/wd4351) ENDIF() + ADD_COMPILE_OPTIONS(/wd4244) #supress warning for double to float conversion if Double precission is activated SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od") + SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi") + SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG:FULL /PDBALTPATH:%_PDB% /OPT:REF /OPT:ICF") ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) IF(NOT ASSIMP_HUNTER_ENABLED) SET(CMAKE_CXX_STANDARD 11) @@ -334,9 +337,9 @@ INCLUDE (FindPkgMacros) INCLUDE (PrecompiledHeader) # Set Assimp project output directory variables. -SET(ASSIMP_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") -SET(ASSIMP_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") -SET(ASSIMP_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib") +SET(ASSIMP_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" CACHE STRING "Path for runtime output files") +SET(ASSIMP_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" CACHE STRING "Path for library output files") +SET(ASSIMP_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib" CACHE STRING "Path for archive output files") # Macro used to set the output directories of a target to the # respective Assimp output directories. @@ -395,14 +398,14 @@ set(GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") IF(ASSIMP_HUNTER_ENABLED) set(CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}") - set(CMAKE_CONFIG_TEMPLATE_FILE "cmake/assimp-hunter-config.cmake.in") + set(CMAKE_CONFIG_TEMPLATE_FILE "cmake-modules/assimp-hunter-config.cmake.in") set(NAMESPACE "${PROJECT_NAME}::") set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") set(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake") set(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}Config.cmake") ELSE() set(CONFIG_INSTALL_DIR "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}") - set(CMAKE_CONFIG_TEMPLATE_FILE "cmake/assimp-plain-config.cmake.in") + set(CMAKE_CONFIG_TEMPLATE_FILE "cmake-modules/assimp-plain-config.cmake.in") string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWERCASE) set(NAMESPACE "${PROJECT_NAME_LOWERCASE}::") set(TARGETS_EXPORT_NAME "${PROJECT_NAME_LOWERCASE}Targets") diff --git a/Readme.md b/Readme.md index f2ea4b094..f4167c9f2 100644 --- a/Readme.md +++ b/Readme.md @@ -42,7 +42,9 @@ Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file. * [.NET](https://bitbucket.org/Starnick/assimpnet/src/master/) * [Pascal](port/AssimpPascal/Readme.md) * [Javascript (Alpha)](https://github.com/makc/assimp2json) -* [Unity 3d Plugin](https://www.assetstore.unity3d.com/en/#!/content/91777) +* [Javascript/Node.js Interface](https://github.com/kovacsv/assimpjs) +* [Unity 3d Plugin](https://ricardoreis.net/trilib-2/) +* [Unreal Engine Plugin](https://github.com/irajsb/UE4_Assimp/) * [JVM](https://github.com/kotlin-graphics/assimp) Full jvm port (current [status](https://github.com/kotlin-graphics/assimp/wiki/Status)) * [HAXE-Port](https://github.com/longde123/assimp-haxe) The Assimp-HAXE-port. * [Rust](https://github.com/jkvargas/russimp) diff --git a/cmake-modules/FindIrrXML.cmake b/cmake-modules/FindIrrXML.cmake deleted file mode 100644 index 5434e0b86..000000000 --- a/cmake-modules/FindIrrXML.cmake +++ /dev/null @@ -1,17 +0,0 @@ -# Find IrrXMl from irrlicht project -# -# Find LibIrrXML headers and library -# -# IRRXML_FOUND - IrrXML found -# IRRXML_INCLUDE_DIR - Headers location -# IRRXML_LIBRARY - IrrXML main library - -find_path(IRRXML_INCLUDE_DIR irrXML.h - PATH_SUFFIXES include/irrlicht include/irrxml) -find_library(IRRXML_LIBRARY IrrXML) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(IrrXML REQUIRED_VARS IRRXML_INCLUDE_DIR IRRXML_LIBRARY) - - -mark_as_advanced(IRRXML_INCLUDE_DIR IRRXML_LIBRARY) diff --git a/cmake/HunterGate.cmake b/cmake-modules/HunterGate.cmake similarity index 100% rename from cmake/HunterGate.cmake rename to cmake-modules/HunterGate.cmake diff --git a/cmake-modules/assimp-hunter-config.cmake.in b/cmake-modules/assimp-hunter-config.cmake.in new file mode 100644 index 000000000..1988f7e7d --- /dev/null +++ b/cmake-modules/assimp-hunter-config.cmake.in @@ -0,0 +1,19 @@ +@PACKAGE_INIT@ + +find_package(RapidJSON CONFIG REQUIRED) +find_package(ZLIB CONFIG REQUIRED) +find_package(utf8cpp CONFIG REQUIRED) +find_package(minizip CONFIG REQUIRED) +find_package(openddlparser CONFIG REQUIRED) +find_package(poly2tri CONFIG REQUIRED) +find_package(polyclipping CONFIG REQUIRED) +find_package(zip CONFIG REQUIRED) +find_package(pugixml CONFIG REQUIRED) +find_package(stb CONFIG REQUIRED) + +if(@ASSIMP_BUILD_DRACO@) + find_package(draco CONFIG REQUIRED) +endif() + +include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake") +check_required_components("@PROJECT_NAME@") diff --git a/cmake/assimp-plain-config.cmake.in b/cmake-modules/assimp-plain-config.cmake.in similarity index 100% rename from cmake/assimp-plain-config.cmake.in rename to cmake-modules/assimp-plain-config.cmake.in diff --git a/cmake/assimp-hunter-config.cmake.in b/cmake/assimp-hunter-config.cmake.in deleted file mode 100644 index 91efcbf24..000000000 --- a/cmake/assimp-hunter-config.cmake.in +++ /dev/null @@ -1,18 +0,0 @@ -@PACKAGE_INIT@ - -find_package(RapidJSON CONFIG REQUIRED) -find_package(ZLIB CONFIG REQUIRED) -find_package(utf8cpp CONFIG REQUIRED) -find_package(minizip CONFIG REQUIRED) -find_package(openddlparser CONFIG REQUIRED) -find_package(poly2tri CONFIG REQUIRED) -find_package(polyclipping CONFIG REQUIRED) -find_package(zip CONFIG REQUIRED) -find_package(pugixml CONFIG REQUIRED) - -if(@ASSIMP_BUILD_DRACO@) - find_package(draco CONFIG REQUIRED) -endif() - -include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake") -check_required_components("@PROJECT_NAME@") diff --git a/code/AssetLib/3DS/3DSConverter.cpp b/code/AssetLib/3DS/3DSConverter.cpp index aca16b0d6..add1553bc 100644 --- a/code/AssetLib/3DS/3DSConverter.cpp +++ b/code/AssetLib/3DS/3DSConverter.cpp @@ -68,8 +68,8 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() { unsigned int idx(NotSet); for (unsigned int i = 0; i < mScene->mMaterials.size(); ++i) { std::string s = mScene->mMaterials[i].mName; - for (std::string::iterator it = s.begin(); it != s.end(); ++it) { - *it = static_cast(::tolower(static_cast(*it))); + for (char & it : s) { + it = static_cast(::tolower(static_cast(it))); } if (std::string::npos == s.find("default")) continue; @@ -79,12 +79,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() { mScene->mMaterials[i].mDiffuse.r != mScene->mMaterials[i].mDiffuse.b) continue; - if (mScene->mMaterials[i].sTexDiffuse.mMapName.length() != 0 || - mScene->mMaterials[i].sTexBump.mMapName.length() != 0 || - mScene->mMaterials[i].sTexOpacity.mMapName.length() != 0 || - mScene->mMaterials[i].sTexEmissive.mMapName.length() != 0 || - mScene->mMaterials[i].sTexSpecular.mMapName.length() != 0 || - mScene->mMaterials[i].sTexShininess.mMapName.length() != 0) { + if (ContainsTextures(i)) { continue; } idx = i; diff --git a/code/AssetLib/3DS/3DSExporter.cpp b/code/AssetLib/3DS/3DSExporter.cpp index 92a6d5aa7..ea92fa12c 100644 --- a/code/AssetLib/3DS/3DSExporter.cpp +++ b/code/AssetLib/3DS/3DSExporter.cpp @@ -56,8 +56,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -using namespace Assimp; namespace Assimp { + using namespace D3DS; namespace { @@ -291,7 +291,7 @@ void Discreet3DSExporter::WriteMaterials() { ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAT_SPECULAR); WriteColor(color); } - + if (mat.Get(AI_MATKEY_COLOR_AMBIENT, color) == AI_SUCCESS) { ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAT_AMBIENT); WriteColor(color); @@ -330,6 +330,7 @@ void Discreet3DSExporter::WriteMaterials() { case aiShadingMode_Blinn: case aiShadingMode_CookTorrance: case aiShadingMode_Fresnel: + case aiShadingMode_PBR_BRDF: // Possibly should be Discreet3DS::Metal in some cases but this is undocumented shading_mode_out = Discreet3DS::Phong; break; @@ -356,7 +357,10 @@ void Discreet3DSExporter::WriteMaterials() { writer.PutI2(1); } - WriteTexture(mat, aiTextureType_DIFFUSE, Discreet3DS::CHUNK_MAT_TEXTURE); + // Fallback to BASE_COLOR if no DIFFUSE + if (!WriteTexture(mat, aiTextureType_DIFFUSE, Discreet3DS::CHUNK_MAT_TEXTURE)) + WriteTexture(mat, aiTextureType_BASE_COLOR, Discreet3DS::CHUNK_MAT_TEXTURE); + WriteTexture(mat, aiTextureType_HEIGHT, Discreet3DS::CHUNK_MAT_BUMPMAP); WriteTexture(mat, aiTextureType_OPACITY, Discreet3DS::CHUNK_MAT_OPACMAP); WriteTexture(mat, aiTextureType_SHININESS, Discreet3DS::CHUNK_MAT_MAT_SHINMAP); @@ -367,20 +371,21 @@ void Discreet3DSExporter::WriteMaterials() { } // ------------------------------------------------------------------------------------------------ -void Discreet3DSExporter::WriteTexture(const aiMaterial &mat, aiTextureType type, uint16_t chunk_flags) { +// returns true if the texture existed +bool Discreet3DSExporter::WriteTexture(const aiMaterial &mat, aiTextureType type, uint16_t chunk_flags) { aiString path; aiTextureMapMode map_mode[2] = { aiTextureMapMode_Wrap, aiTextureMapMode_Wrap }; ai_real blend = 1.0; if (mat.GetTexture(type, 0, &path, nullptr, nullptr, &blend, nullptr, map_mode) != AI_SUCCESS || !path.length) { - return; + return false; } // TODO: handle embedded textures properly if (path.data[0] == '*') { ASSIMP_LOG_ERROR("Ignoring embedded texture for export: ", path.C_Str()); - return; + return false; } ChunkWriter chunk(writer, chunk_flags); @@ -402,6 +407,7 @@ void Discreet3DSExporter::WriteTexture(const aiMaterial &mat, aiTextureType type writer.PutU2(val); } // TODO: export texture transformation (i.e. UV offset, scale, rotation) + return true; } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/3DS/3DSExporter.h b/code/AssetLib/3DS/3DSExporter.h index c48ecb2fc..8ac3da98c 100644 --- a/code/AssetLib/3DS/3DSExporter.h +++ b/code/AssetLib/3DS/3DSExporter.h @@ -73,7 +73,7 @@ public: private: void WriteMeshes(); void WriteMaterials(); - void WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags); + bool WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags); void WriteFaceMaterialChunk(const aiMesh& mesh); int WriteHierarchy(const aiNode& node, int level, int sibling_level); void WriteString(const std::string& s); diff --git a/code/AssetLib/3DS/3DSHelper.h b/code/AssetLib/3DS/3DSHelper.h index 1930c0c40..3a5479de2 100644 --- a/code/AssetLib/3DS/3DSHelper.h +++ b/code/AssetLib/3DS/3DSHelper.h @@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include -#include //sprintf +#include //sprintf namespace Assimp { namespace D3DS { @@ -259,7 +259,7 @@ namespace Discreet3DS { // Specifies the file name of a texture CHUNK_MAPFILE = 0xA300, - // Specifies whether a materail requires two-sided rendering + // Specifies whether a material requires two-sided rendering CHUNK_MAT_TWO_SIDE = 0xA081, // ******************************************************************** @@ -348,16 +348,16 @@ struct Texture { // empty } - Texture(Texture &&other) AI_NO_EXCEPT : mTextureBlend(std::move(other.mTextureBlend)), + Texture(Texture &&other) AI_NO_EXCEPT : mTextureBlend(other.mTextureBlend), mMapName(std::move(other.mMapName)), - mOffsetU(std::move(other.mOffsetU)), - mOffsetV(std::move(other.mOffsetV)), - mScaleU(std::move(other.mScaleU)), - mScaleV(std::move(other.mScaleV)), - mRotation(std::move(other.mRotation)), - mMapMode(std::move(other.mMapMode)), - bPrivate(std::move(other.bPrivate)), - iUVSrc(std::move(other.iUVSrc)) { + mOffsetU(other.mOffsetU), + mOffsetV(other.mOffsetV), + mScaleU(other.mScaleU), + mScaleV(other.mScaleV), + mRotation(other.mRotation), + mMapMode(other.mMapMode), + bPrivate(other.bPrivate), + iUVSrc(other.iUVSrc) { // empty } @@ -366,16 +366,16 @@ struct Texture { return *this; } - mTextureBlend = std::move(other.mTextureBlend); + mTextureBlend = other.mTextureBlend; mMapName = std::move(other.mMapName); - mOffsetU = std::move(other.mOffsetU); - mOffsetV = std::move(other.mOffsetV); - mScaleU = std::move(other.mScaleU); - mScaleV = std::move(other.mScaleV); - mRotation = std::move(other.mRotation); - mMapMode = std::move(other.mMapMode); - bPrivate = std::move(other.bPrivate); - iUVSrc = std::move(other.iUVSrc); + mOffsetU = other.mOffsetU; + mOffsetV = other.mOffsetV; + mScaleU = other.mScaleU; + mScaleV = other.mScaleV; + mRotation = other.mRotation; + mMapMode = other.mMapMode; + bPrivate = other.bPrivate; + iUVSrc = other.iUVSrc; return *this; } @@ -461,13 +461,13 @@ struct Material { //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it Material(Material &&other) AI_NO_EXCEPT : mName(std::move(other.mName)), - mDiffuse(std::move(other.mDiffuse)), - mSpecularExponent(std::move(other.mSpecularExponent)), - mShininessStrength(std::move(other.mShininessStrength)), - mSpecular(std::move(other.mSpecular)), - mAmbient(std::move(other.mAmbient)), - mShading(std::move(other.mShading)), - mTransparency(std::move(other.mTransparency)), + mDiffuse(other.mDiffuse), + mSpecularExponent(other.mSpecularExponent), + mShininessStrength(other.mShininessStrength), + mSpecular(other.mSpecular), + mAmbient(other.mAmbient), + mShading(other.mShading), + mTransparency(other.mTransparency), sTexDiffuse(std::move(other.sTexDiffuse)), sTexOpacity(std::move(other.sTexOpacity)), sTexSpecular(std::move(other.sTexSpecular)), @@ -475,10 +475,10 @@ struct Material { sTexBump(std::move(other.sTexBump)), sTexEmissive(std::move(other.sTexEmissive)), sTexShininess(std::move(other.sTexShininess)), - mBumpHeight(std::move(other.mBumpHeight)), - mEmissive(std::move(other.mEmissive)), + mBumpHeight(other.mBumpHeight), + mEmissive(other.mEmissive), sTexAmbient(std::move(other.sTexAmbient)), - mTwoSided(std::move(other.mTwoSided)) { + mTwoSided(other.mTwoSided) { // empty } @@ -488,13 +488,13 @@ struct Material { } mName = std::move(other.mName); - mDiffuse = std::move(other.mDiffuse); - mSpecularExponent = std::move(other.mSpecularExponent); - mShininessStrength = std::move(other.mShininessStrength), - mSpecular = std::move(other.mSpecular); - mAmbient = std::move(other.mAmbient); - mShading = std::move(other.mShading); - mTransparency = std::move(other.mTransparency); + mDiffuse = other.mDiffuse; + mSpecularExponent = other.mSpecularExponent; + mShininessStrength = other.mShininessStrength, + mSpecular = other.mSpecular; + mAmbient = other.mAmbient; + mShading = other.mShading; + mTransparency = other.mTransparency; sTexDiffuse = std::move(other.sTexDiffuse); sTexOpacity = std::move(other.sTexOpacity); sTexSpecular = std::move(other.sTexSpecular); @@ -502,10 +502,10 @@ struct Material { sTexBump = std::move(other.sTexBump); sTexEmissive = std::move(other.sTexEmissive); sTexShininess = std::move(other.sTexShininess); - mBumpHeight = std::move(other.mBumpHeight); - mEmissive = std::move(other.mEmissive); + mBumpHeight = other.mBumpHeight; + mEmissive = other.mEmissive; sTexAmbient = std::move(other.sTexAmbient); - mTwoSided = std::move(other.mTwoSided); + mTwoSided = other.mTwoSided; return *this; } diff --git a/code/AssetLib/3DS/3DSLoader.cpp b/code/AssetLib/3DS/3DSLoader.cpp index b5e6f749b..05b5117ba 100644 --- a/code/AssetLib/3DS/3DSLoader.cpp +++ b/code/AssetLib/3DS/3DSLoader.cpp @@ -449,7 +449,7 @@ void Discreet3DSImporter::ParseChunk(const char *name, unsigned int num) { // Read the lense angle camera->mHorizontalFOV = AI_DEG_TO_RAD(stream->GetF4()); if (camera->mHorizontalFOV < 0.001f) { - camera->mHorizontalFOV = AI_DEG_TO_RAD(45.f); + camera->mHorizontalFOV = float(AI_DEG_TO_RAD(45.f)); } // Now check for further subchunks diff --git a/code/AssetLib/3DS/3DSLoader.h b/code/AssetLib/3DS/3DSLoader.h index 2091fbeb7..bd167872f 100644 --- a/code/AssetLib/3DS/3DSLoader.h +++ b/code/AssetLib/3DS/3DSLoader.h @@ -46,11 +46,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef AI_3DSIMPORTER_H_INC #define AI_3DSIMPORTER_H_INC +#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER #include #include -#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER #include "3DSHelper.h" #include @@ -75,14 +75,14 @@ public: * See BaseImporter::CanRead() for details. */ bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; + bool checkSig) const override; // ------------------------------------------------------------------- /** Called prior to ReadFile(). * The function is a request to the importer to update its configuration * basing on the Importer's configuration property list. */ - void SetupProperties(const Importer* pImp); + void SetupProperties(const Importer* pImp) override; protected: @@ -90,14 +90,14 @@ protected: /** Return importer meta information. * See #BaseImporter::GetInfo for the details */ - const aiImporterDesc* GetInfo () const; + const aiImporterDesc* GetInfo () const override; // ------------------------------------------------------------------- /** Imports the given file into the given scene structure. * See BaseImporter::InternReadFile() for details */ void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); + IOSystem* pIOHandler) override; // ------------------------------------------------------------------- /** Converts a temporary material to the outer representation @@ -208,6 +208,15 @@ protected: */ void ReplaceDefaultMaterial(); + bool ContainsTextures(unsigned int i) const { + return !mScene->mMaterials[i].sTexDiffuse.mMapName.empty() || + !mScene->mMaterials[i].sTexBump.mMapName.empty() || + !mScene->mMaterials[i].sTexOpacity.mMapName.empty() || + !mScene->mMaterials[i].sTexEmissive.mMapName.empty() || + !mScene->mMaterials[i].sTexSpecular.mMapName.empty() || + !mScene->mMaterials[i].sTexShininess.mMapName.empty() ; + } + // ------------------------------------------------------------------- /** Convert the whole scene */ diff --git a/code/AssetLib/3MF/3MFTypes.h b/code/AssetLib/3MF/3MFTypes.h new file mode 100644 index 000000000..c4e9e4243 --- /dev/null +++ b/code/AssetLib/3MF/3MFTypes.h @@ -0,0 +1,165 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2021, 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. + +---------------------------------------------------------------------- +*/ +#pragma once + +#include +#include +#include +#include +#include + +struct aiMaterial; +struct aiMesh; + +namespace Assimp { +namespace D3MF { + +enum class ResourceType { + RT_Object, + RT_BaseMaterials, + RT_EmbeddedTexture2D, + RT_Texture2DGroup, + RT_Unknown +}; // To be extended with other resource types (eg. material extension resources like Texture2d, Texture2dGroup...) + +class Resource { +public: + int mId; + + Resource(int id) : + mId(id) { + // empty + } + + virtual ~Resource() { + // empty + } + + virtual ResourceType getType() const { + return ResourceType::RT_Unknown; + } +}; + +class EmbeddedTexture : public Resource { +public: + std::string mPath; + std::string mContentType; + std::string mTilestyleU; + std::string mTilestyleV; + std::vector mBuffer; + + EmbeddedTexture(int id) : + Resource(id), + mPath(), + mContentType(), + mTilestyleU(), + mTilestyleV() { + // empty + } + + ~EmbeddedTexture() = default; + + ResourceType getType() const override { + return ResourceType::RT_EmbeddedTexture2D; + } +}; + +class Texture2DGroup : public Resource { +public: + std::vector mTex2dCoords; + int mTexId; + Texture2DGroup(int id) : + Resource(id), + mTexId(-1) { + // empty + } + + ~Texture2DGroup() = default; + + ResourceType getType() const override { + return ResourceType::RT_Texture2DGroup; + } +}; + +class BaseMaterials : public Resource { +public: + std::vector mMaterialIndex; + + BaseMaterials(int id) : + Resource(id), + mMaterialIndex() { + // empty + } + + ~BaseMaterials() = default; + + ResourceType getType() const override { + return ResourceType::RT_BaseMaterials; + } +}; + +struct Component { + int mObjectId; + aiMatrix4x4 mTransformation; +}; + +class Object : public Resource { +public: + std::vector mMeshes; + std::vector mMeshIndex; + std::vector mComponents; + std::string mName; + + Object(int id) : + Resource(id), + mName(std::string("Object_") + ai_to_string(id)) { + // empty + } + + ~Object() = default; + + ResourceType getType() const override { + return ResourceType::RT_Object; + } +}; + +} // namespace D3MF +} // namespace Assimp diff --git a/code/AssetLib/3MF/3MFXmlTags.h b/code/AssetLib/3MF/3MFXmlTags.h index d447556d6..a6e9758c1 100644 --- a/code/AssetLib/3MF/3MFXmlTags.h +++ b/code/AssetLib/3MF/3MFXmlTags.h @@ -80,13 +80,21 @@ namespace XmlTag { const char* const item = "item"; const char* const objectid = "objectid"; const char* const transform = "transform"; + const char *const path = "path"; // Material definitions const char* const basematerials = "basematerials"; - const char* const basematerials_id = "id"; const char* const basematerials_base = "base"; const char* const basematerials_name = "name"; const char* const basematerials_displaycolor = "displaycolor"; + const char* const texture_2d = "m:texture2d"; + const char *const texture_group = "m:texture2dgroup"; + const char *const texture_content_type = "contenttype"; + const char *const texture_tilestyleu = "tilestyleu"; + const char *const texture_tilestylev = "tilestylev"; + const char *const texture_2d_coord = "m:tex2coord"; + const char *const texture_cuurd_u = "u"; + const char *const texture_cuurd_v = "v"; // Meta info tags const char* const CONTENT_TYPES_ARCHIVE = "[Content_Types].xml"; @@ -103,7 +111,7 @@ namespace XmlTag { const char* const PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture"; const char* const PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"; const char* const PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"; - } +} } // Namespace D3MF } // Namespace Assimp diff --git a/code/AssetLib/3MF/D3MFExporter.h b/code/AssetLib/3MF/D3MFExporter.h index d2fc82483..df25e305e 100644 --- a/code/AssetLib/3MF/D3MFExporter.h +++ b/code/AssetLib/3MF/D3MFExporter.h @@ -40,6 +40,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once +#ifndef ASSIMP_BUILD_NO_EXPORT +#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER + #include #include #include @@ -58,8 +61,6 @@ class IOStream; namespace D3MF { -#ifndef ASSIMP_BUILD_NO_EXPORT -#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER struct OpcPackageRelationship; @@ -100,9 +101,11 @@ private: std::vector mRelations; }; -#endif // ASSIMP_BUILD_NO_3MF_EXPORTER -#endif // ASSIMP_BUILD_NO_EXPORT } // Namespace D3MF } // Namespace Assimp +#endif // ASSIMP_BUILD_NO_3MF_EXPORTER +#endif // ASSIMP_BUILD_NO_EXPORT + + diff --git a/code/AssetLib/3MF/D3MFImporter.cpp b/code/AssetLib/3MF/D3MFImporter.cpp index 747af7cfc..58dde9738 100644 --- a/code/AssetLib/3MF/D3MFImporter.cpp +++ b/code/AssetLib/3MF/D3MFImporter.cpp @@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "D3MFImporter.h" #include "3MFXmlTags.h" #include "D3MFOpcPackage.h" +#include "XmlSerializer.h" #include #include @@ -61,513 +62,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include -#include +#include namespace Assimp { -namespace D3MF { - -enum class ResourceType { - RT_Object, - RT_BaseMaterials, - RT_Unknown -}; // To be extended with other resource types (eg. material extension resources like Texture2d, Texture2dGroup...) - -class Resource { -public: - int mId; - - Resource(int id) : - mId(id) { - // empty - } - - virtual ~Resource() { - // empty - } - - virtual ResourceType getType() const { - return ResourceType::RT_Unknown; - } -}; - -class BaseMaterials : public Resource { -public: - std::vector mMaterials; - std::vector mMaterialIndex; - - BaseMaterials(int id) : - Resource(id), - mMaterials(), - mMaterialIndex() { - // empty - } - - ~BaseMaterials() = default; - - ResourceType getType() const override { - return ResourceType::RT_BaseMaterials; - } -}; - -struct Component { - int mObjectId; - aiMatrix4x4 mTransformation; -}; - -class Object : public Resource { -public: - std::vector mMeshes; - std::vector mMeshIndex; - std::vector mComponents; - std::string mName; - - Object(int id) : - Resource(id), - mName(std::string("Object_") + ai_to_string(id)) { - // empty - } - - ~Object() = default; - - ResourceType getType() const override { - return ResourceType::RT_Object; - } -}; - -class XmlSerializer { -public: - XmlSerializer(XmlParser *xmlParser) : - mResourcesDictionnary(), - mMaterialCount(0), - mMeshCount(0), - mXmlParser(xmlParser) { - // empty - } - - ~XmlSerializer() { - for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it ) { - delete it->second; - } - } - - void ImportXml(aiScene *scene) { - if (nullptr == scene) { - return; - } - - scene->mRootNode = new aiNode(XmlTag::RootTag); - - XmlNode node = mXmlParser->getRootNode().child(XmlTag::model); - if (node.empty()) { - return; - } - XmlNode resNode = node.child(XmlTag::resources); - for (auto ¤tNode : resNode.children()) { - const std::string currentNodeName = currentNode.name(); - if (currentNodeName == XmlTag::object) { - ReadObject(currentNode); - } else if (currentNodeName == XmlTag::basematerials) { - ReadBaseMaterials(currentNode); - } else if (currentNodeName == XmlTag::meta) { - ReadMetadata(currentNode); - } - } - - XmlNode buildNode = node.child(XmlTag::build); - for (auto ¤tNode : buildNode.children()) { - const std::string currentNodeName = currentNode.name(); - if (currentNodeName == XmlTag::item) { - int objectId = -1; - std::string transformationMatrixStr; - aiMatrix4x4 transformationMatrix; - getNodeAttribute(currentNode, D3MF::XmlTag::objectid, objectId); - bool hasTransform = getNodeAttribute(currentNode, D3MF::XmlTag::transform, transformationMatrixStr); - - auto it = mResourcesDictionnary.find(objectId); - if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) { - Object *obj = static_cast(it->second); - if (hasTransform) { - transformationMatrix = parseTransformMatrix(transformationMatrixStr); - } - - addObjectToNode(scene->mRootNode, obj, transformationMatrix); - } - } - } - - // import the metadata - if (!mMetaData.empty()) { - const size_t numMeta = mMetaData.size(); - scene->mMetaData = aiMetadata::Alloc(static_cast(numMeta)); - for (size_t i = 0; i < numMeta; ++i) { - aiString val(mMetaData[i].value); - scene->mMetaData->Set(static_cast(i), mMetaData[i].name, val); - } - } - - // import the meshes - scene->mNumMeshes = static_cast(mMeshCount); - if (scene->mNumMeshes != 0) { - scene->mMeshes = new aiMesh *[scene->mNumMeshes](); - for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it) { - if (it->second->getType() == ResourceType::RT_Object) { - Object *obj = static_cast(it->second); - ai_assert(nullptr != obj); - for (unsigned int i = 0; i < obj->mMeshes.size(); ++i) { - scene->mMeshes[obj->mMeshIndex[i]] = obj->mMeshes[i]; - } - } - } - } - - // import the materials - scene->mNumMaterials = mMaterialCount; - if (scene->mNumMaterials != 0) { - scene->mMaterials = new aiMaterial *[scene->mNumMaterials]; - for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it) { - if (it->second->getType() == ResourceType::RT_BaseMaterials) { - BaseMaterials *baseMaterials = static_cast(it->second); - for (unsigned int i = 0; i < baseMaterials->mMaterials.size(); ++i) { - scene->mMaterials[baseMaterials->mMaterialIndex[i]] = baseMaterials->mMaterials[i]; - } - } - } - } - } - -private: - void addObjectToNode(aiNode *parent, Object *obj, aiMatrix4x4 nodeTransform) { - ai_assert(nullptr != obj); - - aiNode *sceneNode = new aiNode(obj->mName); - sceneNode->mNumMeshes = static_cast(obj->mMeshes.size()); - sceneNode->mMeshes = new unsigned int[sceneNode->mNumMeshes]; - std::copy(obj->mMeshIndex.begin(), obj->mMeshIndex.end(), sceneNode->mMeshes); - - sceneNode->mTransformation = nodeTransform; - if (nullptr != parent) { - parent->addChildren(1, &sceneNode); - } - - for (size_t i = 0; i < obj->mComponents.size(); ++i) { - Component c = obj->mComponents[i]; - auto it = mResourcesDictionnary.find(c.mObjectId); - if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) { - addObjectToNode(sceneNode, static_cast(it->second), c.mTransformation); - } - } - } - - bool getNodeAttribute(const XmlNode &node, const std::string &attribute, std::string &value) { - pugi::xml_attribute objectAttribute = node.attribute(attribute.c_str()); - if (!objectAttribute.empty()) { - value = objectAttribute.as_string(); - return true; - } - - return false; - } - - bool getNodeAttribute(const XmlNode &node, const std::string &attribute, int &value) { - std::string strValue; - bool ret = getNodeAttribute(node, attribute, strValue); - if (ret) { - value = std::atoi(strValue.c_str()); - return true; - } - - return false; - } - - aiMatrix4x4 parseTransformMatrix(std::string matrixStr) { - // split the string - std::vector numbers; - std::string currentNumber; - for (size_t i = 0; i < matrixStr.size(); ++i) { - const char c = matrixStr[i]; - if (c == ' ') { - if (currentNumber.size() > 0) { - float f = std::stof(currentNumber); - numbers.push_back(f); - currentNumber.clear(); - } - } else { - currentNumber.push_back(c); - } - } - if (currentNumber.size() > 0) { - const float f = std::stof(currentNumber); - numbers.push_back(f); - } - - aiMatrix4x4 transformMatrix; - transformMatrix.a1 = numbers[0]; - transformMatrix.b1 = numbers[1]; - transformMatrix.c1 = numbers[2]; - transformMatrix.d1 = 0; - - transformMatrix.a2 = numbers[3]; - transformMatrix.b2 = numbers[4]; - transformMatrix.c2 = numbers[5]; - transformMatrix.d2 = 0; - - transformMatrix.a3 = numbers[6]; - transformMatrix.b3 = numbers[7]; - transformMatrix.c3 = numbers[8]; - transformMatrix.d3 = 0; - - transformMatrix.a4 = numbers[9]; - transformMatrix.b4 = numbers[10]; - transformMatrix.c4 = numbers[11]; - transformMatrix.d4 = 1; - - return transformMatrix; - } - - void ReadObject(XmlNode &node) { - int id = -1, pid = -1, pindex = -1; - bool hasId = getNodeAttribute(node, XmlTag::id, id); - bool hasPid = getNodeAttribute(node, XmlTag::pid, pid); - bool hasPindex = getNodeAttribute(node, XmlTag::pindex, pindex); - if (!hasId) { - return; - } - - Object *obj = new Object(id); - - for (XmlNode ¤tNode : node.children()) { - const std::string ¤tName = currentNode.name(); - if (currentName == D3MF::XmlTag::mesh) { - auto mesh = ReadMesh(currentNode); - mesh->mName.Set(ai_to_string(id)); - - if (hasPid) { - auto it = mResourcesDictionnary.find(pid); - if (hasPindex && it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_BaseMaterials) { - BaseMaterials *materials = static_cast(it->second); - mesh->mMaterialIndex = materials->mMaterialIndex[pindex]; - } - } - - obj->mMeshes.push_back(mesh); - obj->mMeshIndex.push_back(mMeshCount); - mMeshCount++; - } else if (currentName == D3MF::XmlTag::components) { - for (XmlNode ¤tSubNode : currentNode.children()) { - const std::string subNodeName = currentSubNode.name(); - if (subNodeName == D3MF::XmlTag::component) { - int objectId = -1; - std::string componentTransformStr; - aiMatrix4x4 componentTransform; - if (getNodeAttribute(currentSubNode, D3MF::XmlTag::transform, componentTransformStr)) { - componentTransform = parseTransformMatrix(componentTransformStr); - } - - if (getNodeAttribute(currentSubNode, D3MF::XmlTag::objectid, objectId)) { - obj->mComponents.push_back({ objectId, componentTransform }); - } - } - } - } - } - - mResourcesDictionnary.insert(std::make_pair(id, obj)); - } - - aiMesh *ReadMesh(XmlNode &node) { - aiMesh *mesh = new aiMesh(); - - for (XmlNode ¤tNode : node.children()) { - const std::string currentName = currentNode.name(); - if (currentName == XmlTag::vertices) { - ImportVertices(currentNode, mesh); - } else if (currentName == XmlTag::triangles) { - ImportTriangles(currentNode, mesh); - } - } - - return mesh; - } - - void ReadMetadata(XmlNode &node) { - pugi::xml_attribute attribute = node.attribute(D3MF::XmlTag::meta_name); - const std::string name = attribute.as_string(); - const std::string value = node.value(); - if (name.empty()) { - return; - } - - MetaEntry entry; - entry.name = name; - entry.value = value; - mMetaData.push_back(entry); - } - - void ImportVertices(XmlNode &node, aiMesh *mesh) { - std::vector vertices; - for (XmlNode ¤tNode : node.children()) { - const std::string currentName = currentNode.name(); - if (currentName == XmlTag::vertex) { - vertices.push_back(ReadVertex(currentNode)); - } - } - - mesh->mNumVertices = static_cast(vertices.size()); - mesh->mVertices = new aiVector3D[mesh->mNumVertices]; - std::copy(vertices.begin(), vertices.end(), mesh->mVertices); - } - - aiVector3D ReadVertex(XmlNode &node) { - aiVector3D vertex; - vertex.x = ai_strtof(node.attribute(XmlTag::x).as_string(), nullptr); - vertex.y = ai_strtof(node.attribute(XmlTag::y).as_string(), nullptr); - vertex.z = ai_strtof(node.attribute(XmlTag::z).as_string(), nullptr); - - return vertex; - } - - void ImportTriangles(XmlNode &node, aiMesh *mesh) { - std::vector faces; - for (XmlNode ¤tNode : node.children()) { - const std::string currentName = currentNode.name(); - if (currentName == XmlTag::triangle) { - aiFace face = ReadTriangle(currentNode); - faces.push_back(face); - - int pid = 0, p1 = 0; - bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid); - bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1); - - if (hasPid && hasP1) { - auto it = mResourcesDictionnary.find(pid); - if (it != mResourcesDictionnary.end()) { - if (it->second->getType() == ResourceType::RT_BaseMaterials) { - BaseMaterials *baseMaterials = static_cast(it->second); - mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1]; - } - // TODO: manage the separation into several meshes if the triangles of the mesh do not all refer to the same material - } - } - } - } - - mesh->mNumFaces = static_cast(faces.size()); - mesh->mFaces = new aiFace[mesh->mNumFaces]; - mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - - std::copy(faces.begin(), faces.end(), mesh->mFaces); - } - - aiFace ReadTriangle(XmlNode &node) { - aiFace face; - - face.mNumIndices = 3; - face.mIndices = new unsigned int[face.mNumIndices]; - face.mIndices[0] = static_cast(std::atoi(node.attribute(XmlTag::v1).as_string())); - 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())); - - return face; - } - - void ReadBaseMaterials(XmlNode &node) { - int id = -1; - if (getNodeAttribute(node, D3MF::XmlTag::basematerials_id, id)) { - BaseMaterials *baseMaterials = new BaseMaterials(id); - - for (XmlNode ¤tNode : node.children()) { - const std::string currentName = currentNode.name(); - if (currentName == XmlTag::basematerials_base) { - baseMaterials->mMaterialIndex.push_back(mMaterialCount); - baseMaterials->mMaterials.push_back(readMaterialDef(currentNode, id)); - ++mMaterialCount; - } - } - - mResourcesDictionnary.insert(std::make_pair(id, baseMaterials)); - } - } - - bool parseColor(const char *color, aiColor4D &diffuse) { - if (nullptr == color) { - return false; - } - - //format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1) - const size_t len = strlen(color); - if (9 != len && 7 != len) { - return false; - } - - const char *buf(color); - if ('#' != buf[0]) { - return false; - } - - char r[3] = { buf[1], buf[2], '\0' }; - diffuse.r = static_cast(strtol(r, nullptr, 16)) / ai_real(255.0); - - char g[3] = { buf[3], buf[4], '\0' }; - diffuse.g = static_cast(strtol(g, nullptr, 16)) / ai_real(255.0); - - char b[3] = { buf[5], buf[6], '\0' }; - diffuse.b = static_cast(strtol(b, nullptr, 16)) / ai_real(255.0); - - if (7 == len) - return true; - - char a[3] = { buf[7], buf[8], '\0' }; - diffuse.a = static_cast(strtol(a, nullptr, 16)) / ai_real(255.0); - - return true; - } - - void assignDiffuseColor(XmlNode &node, aiMaterial *mat) { - const char *color = node.attribute(XmlTag::basematerials_displaycolor).as_string(); - aiColor4D diffuse; - if (parseColor(color, diffuse)) { - mat->AddProperty(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE); - } - } - - aiMaterial *readMaterialDef(XmlNode &node, unsigned int basematerialsId) { - aiMaterial *material = new aiMaterial(); - material->mNumProperties = 0; - std::string name; - bool hasName = getNodeAttribute(node, D3MF::XmlTag::basematerials_name, name); - - std::string stdMaterialName; - const std::string strId(ai_to_string(basematerialsId)); - stdMaterialName += "id"; - stdMaterialName += strId; - stdMaterialName += "_"; - if (hasName) { - stdMaterialName += std::string(name); - } else { - stdMaterialName += "basemat_"; - stdMaterialName += ai_to_string(mMaterialCount - basematerialsId); - } - - aiString assimpMaterialName(stdMaterialName); - material->AddProperty(&assimpMaterialName, AI_MATKEY_NAME); - - assignDiffuseColor(node, material); - - return material; - } - -private: - struct MetaEntry { - std::string name; - std::string value; - }; - std::vector mMetaData; - std::map mResourcesDictionnary; - unsigned int mMaterialCount, mMeshCount; - XmlParser *mXmlParser; -}; - -} //namespace D3MF using namespace D3MF; @@ -597,7 +94,9 @@ bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bo const std::string extension(GetExtension(filename)); if (extension == desc.mFileExtensions) { return true; - } else if (!extension.length() || checkSig) { + } + + if (!extension.length() || checkSig) { if (nullptr == pIOHandler) { return false; } @@ -611,7 +110,7 @@ bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bo return false; } -void D3MFImporter::SetupProperties(const Importer * /*pImp*/) { +void D3MFImporter::SetupProperties(const Importer*) { // empty } @@ -626,6 +125,15 @@ void D3MFImporter::InternReadFile(const std::string &filename, aiScene *pScene, if (xmlParser.parse(opcPackage.RootStream())) { XmlSerializer xmlSerializer(&xmlParser); xmlSerializer.ImportXml(pScene); + + const std::vector &tex = opcPackage.GetEmbeddedTextures(); + if (!tex.empty()) { + pScene->mNumTextures = static_cast(tex.size()); + pScene->mTextures = new aiTexture *[pScene->mNumTextures]; + for (unsigned int i = 0; i < pScene->mNumTextures; ++i) { + pScene->mTextures[i] = tex[i]; + } + } } } diff --git a/code/AssetLib/3MF/D3MFImporter.h b/code/AssetLib/3MF/D3MFImporter.h index 811c463b6..7219fa39d 100644 --- a/code/AssetLib/3MF/D3MFImporter.h +++ b/code/AssetLib/3MF/D3MFImporter.h @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2021, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -43,23 +42,50 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_D3MFLOADER_H_INCLUDED #define AI_D3MFLOADER_H_INCLUDED +#ifndef ASSIMP_BUILD_NO_3MF_IMPORTER + #include namespace Assimp { +// --------------------------------------------------------------------------- /// @brief The 3MF-importer class. +/// +/// Implements the basic topology import and embedded textures. +// --------------------------------------------------------------------------- class D3MFImporter : public BaseImporter { public: + /// @brief The default class constructor. D3MFImporter(); - ~D3MFImporter(); - bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const; - void SetupProperties(const Importer *pImp); - const aiImporterDesc *GetInfo() const; + + /// @brief The class destructor. + ~D3MFImporter() override; + + /// @brief Performs the data format detection. + /// @param pFile The filename to check. + /// @param pIOHandler The used IO-System. + /// @param checkSig true for signature checking. + /// @return true for can be loaded, false for not. + bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const override; + + /// @brief Not used + /// @param pImp Not used + void SetupProperties(const Importer *pImp) override; + + /// @brief The importer description getter. + /// @return The info + const aiImporterDesc *GetInfo() const override; protected: - void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler); + /// @brief Internal read function, performs the file parsing. + /// @param pFile The filename + /// @param pScene The scene to load in. + /// @param pIOHandler The io-system + void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override; }; } // Namespace Assimp +#endif // #ifndef ASSIMP_BUILD_NO_3MF_IMPORTER + #endif // AI_D3MFLOADER_H_INCLUDED diff --git a/code/AssetLib/3MF/D3MFOpcPackage.cpp b/code/AssetLib/3MF/D3MFOpcPackage.cpp index dbf4f2e10..8d51a7417 100644 --- a/code/AssetLib/3MF/D3MFOpcPackage.cpp +++ b/code/AssetLib/3MF/D3MFOpcPackage.cpp @@ -43,20 +43,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "D3MFOpcPackage.h" #include - #include #include #include #include #include #include - +#include #include "3MFXmlTags.h" + #include #include #include #include -#include #include namespace Assimp { @@ -64,11 +63,12 @@ namespace Assimp { namespace D3MF { // ------------------------------------------------------------------------------------------------ -typedef std::shared_ptr OpcPackageRelationshipPtr; +using OpcPackageRelationshipPtr = std::shared_ptr; class OpcPackageRelationshipReader { public: - OpcPackageRelationshipReader(XmlParser &parser) { + OpcPackageRelationshipReader(XmlParser &parser) : + m_relationShips() { XmlNode root = parser.getRootNode(); ParseRootNode(root); } @@ -91,6 +91,7 @@ public: if (relPtr->id.empty() || relPtr->type.empty() || relPtr->target.empty()) { return false; } + return true; } @@ -100,7 +101,7 @@ public: } for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { - std::string name = currentNode.name(); + const std::string name = currentNode.name(); if (name == "Relationship") { OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship()); relPtr->id = currentNode.attribute(XmlTag::RELS_ATTRIB_ID).as_string(); @@ -116,11 +117,23 @@ public: std::vector m_relationShips; }; +static bool IsEmbeddedTexture( const std::string &filename ) { + const std::string extension = BaseImporter::GetExtension(filename); + if (extension == "jpg" || extension == "png") { + std::string::size_type pos = filename.find("thumbnail"); + if (pos == std::string::npos) { + return false; + } + return true; + } + + return false; +} // ------------------------------------------------------------------------------------------------ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) : mRootStream(nullptr), mZipArchive() { - mZipArchive.reset(new ZipArchiveIOSystem(pIOHandler, rFile)); + mZipArchive = new ZipArchiveIOSystem(pIOHandler, rFile); if (!mZipArchive->isOpen()) { throw DeadlyImportError("Failed to open file ", rFile, "."); } @@ -136,18 +149,18 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) : IOStream *fileStream = mZipArchive->Open(file.c_str()); if (nullptr == fileStream) { - ai_assert(fileStream != nullptr); + ASSIMP_LOG_ERROR("Filestream is nullptr."); continue; } std::string rootFile = ReadPackageRootRelationship(fileStream); - if (rootFile.size() > 0 && rootFile[0] == '/') { + if (!rootFile.empty() && rootFile[0] == '/') { rootFile = rootFile.substr(1); if (rootFile[0] == '/') { // deal with zip-bug rootFile = rootFile.substr(1); } - } + } ASSIMP_LOG_VERBOSE_DEBUG(rootFile); @@ -158,9 +171,12 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) : if (nullptr == mRootStream) { throw DeadlyImportError("Cannot open root-file in archive : " + rootFile); } - } else if (file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) { ASSIMP_LOG_WARN("Ignored file of unsupported type CONTENT_TYPES_ARCHIVES", file); + } else if (IsEmbeddedTexture(file)) { + IOStream *fileStream = mZipArchive->Open(file.c_str()); + LoadEmbeddedTextures(fileStream, file); + mZipArchive->Close(fileStream); } else { ASSIMP_LOG_WARN("Ignored file of unknown type: ", file); } @@ -169,20 +185,25 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) : D3MFOpcPackage::~D3MFOpcPackage() { mZipArchive->Close(mRootStream); + delete mZipArchive; } IOStream *D3MFOpcPackage::RootStream() const { return mRootStream; } -static const std::string ModelRef = "3D/3dmodel.model"; +const std::vector &D3MFOpcPackage::GetEmbeddedTextures() const { + return mEmbeddedTextures; +} + +static const char *const ModelRef = "3D/3dmodel.model"; bool D3MFOpcPackage::validate() { if (nullptr == mRootStream || nullptr == mZipArchive) { return false; } - return mZipArchive->Exists(ModelRef.c_str()); + return mZipArchive->Exists(ModelRef); } std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) { @@ -204,6 +225,31 @@ std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) { return (*itr)->target; } +void D3MFOpcPackage::LoadEmbeddedTextures(IOStream *fileStream, const std::string &filename) { + if (nullptr == fileStream) { + return; + } + + const size_t size = fileStream->FileSize(); + if (0 == size) { + return; + } + + unsigned char *data = new unsigned char[size]; + fileStream->Read(data, 1, size); + aiTexture *texture = new aiTexture; + std::string embName = "*" + filename; + texture->mFilename.Set(embName.c_str()); + texture->mWidth = static_cast(size); + texture->mHeight = 0; + texture->achFormatHint[0] = 'p'; + texture->achFormatHint[1] = 'n'; + texture->achFormatHint[2] = 'g'; + texture->achFormatHint[3] = '\0'; + texture->pcData = (aiTexel*) data; + mEmbeddedTextures.emplace_back(texture); +} + } // Namespace D3MF } // Namespace Assimp diff --git a/code/AssetLib/3MF/D3MFOpcPackage.h b/code/AssetLib/3MF/D3MFOpcPackage.h index 22b4510d0..27bf44ff2 100644 --- a/code/AssetLib/3MF/D3MFOpcPackage.h +++ b/code/AssetLib/3MF/D3MFOpcPackage.h @@ -42,12 +42,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef D3MFOPCPACKAGE_H #define D3MFOPCPACKAGE_H +#include #include #include -#include + +struct aiTexture; namespace Assimp { - class ZipArchiveIOSystem; + +class ZipArchiveIOSystem; namespace D3MF { @@ -63,16 +66,19 @@ public: ~D3MFOpcPackage(); IOStream* RootStream() const; bool validate(); + const std::vector &GetEmbeddedTextures() const; protected: std::string ReadPackageRootRelationship(IOStream* stream); + void LoadEmbeddedTextures(IOStream *fileStream, const std::string &filename); private: IOStream* mRootStream; - std::unique_ptr mZipArchive; + ZipArchiveIOSystem *mZipArchive; + std::vector mEmbeddedTextures; }; -} // Namespace D3MF -} // Namespace Assimp +} // namespace D3MF +} // namespace Assimp #endif // D3MFOPCPACKAGE_H diff --git a/code/AssetLib/3MF/XmlSerializer.cpp b/code/AssetLib/3MF/XmlSerializer.cpp new file mode 100644 index 000000000..985286fa7 --- /dev/null +++ b/code/AssetLib/3MF/XmlSerializer.cpp @@ -0,0 +1,593 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2021, 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 "XmlSerializer.h" +#include "D3MFOpcPackage.h" +#include "3MFXmlTags.h" +#include "3MFTypes.h" +#include + +namespace Assimp { +namespace D3MF { + +static const int IdNotSet = -1; + +namespace { + +static const size_t ColRGBA_Len = 9; +static const size_t ColRGB_Len = 7; + +// format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1) +bool validateColorString(const char *color) { + const size_t len = strlen(color); + if (ColRGBA_Len != len && ColRGB_Len != len) { + return false; + } + + return true; +} + +aiFace ReadTriangle(XmlNode &node) { + aiFace face; + + face.mNumIndices = 3; + face.mIndices = new unsigned int[face.mNumIndices]; + face.mIndices[0] = static_cast(std::atoi(node.attribute(XmlTag::v1).as_string())); + 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())); + + return face; +} + +aiVector3D ReadVertex(XmlNode &node) { + aiVector3D vertex; + vertex.x = ai_strtof(node.attribute(XmlTag::x).as_string(), nullptr); + vertex.y = ai_strtof(node.attribute(XmlTag::y).as_string(), nullptr); + vertex.z = ai_strtof(node.attribute(XmlTag::z).as_string(), nullptr); + + return vertex; +} + +bool getNodeAttribute(const XmlNode &node, const std::string &attribute, std::string &value) { + pugi::xml_attribute objectAttribute = node.attribute(attribute.c_str()); + if (!objectAttribute.empty()) { + value = objectAttribute.as_string(); + return true; + } + + return false; +} + +bool getNodeAttribute(const XmlNode &node, const std::string &attribute, int &value) { + std::string strValue; + const bool ret = getNodeAttribute(node, attribute, strValue); + if (ret) { + value = std::atoi(strValue.c_str()); + return true; + } + + return false; +} + +aiMatrix4x4 parseTransformMatrix(std::string matrixStr) { + // split the string + std::vector numbers; + std::string currentNumber; + for (char c : matrixStr) { + if (c == ' ') { + if (!currentNumber.empty()) { + float f = std::stof(currentNumber); + numbers.push_back(f); + currentNumber.clear(); + } + } else { + currentNumber.push_back(c); + } + } + if (!currentNumber.empty()) { + const float f = std::stof(currentNumber); + numbers.push_back(f); + } + + aiMatrix4x4 transformMatrix; + transformMatrix.a1 = numbers[0]; + transformMatrix.b1 = numbers[1]; + transformMatrix.c1 = numbers[2]; + transformMatrix.d1 = 0; + + transformMatrix.a2 = numbers[3]; + transformMatrix.b2 = numbers[4]; + transformMatrix.c2 = numbers[5]; + transformMatrix.d2 = 0; + + transformMatrix.a3 = numbers[6]; + transformMatrix.b3 = numbers[7]; + transformMatrix.c3 = numbers[8]; + transformMatrix.d3 = 0; + + transformMatrix.a4 = numbers[9]; + transformMatrix.b4 = numbers[10]; + transformMatrix.c4 = numbers[11]; + transformMatrix.d4 = 1; + + return transformMatrix; +} + +bool parseColor(const char *color, aiColor4D &diffuse) { + if (nullptr == color) { + return false; + } + + if (!validateColorString(color)) { + return false; + } + + if ('#' != color[0]) { + return false; + } + + char r[3] = { color[1], color[2], '\0' }; + diffuse.r = static_cast(strtol(r, nullptr, 16)) / ai_real(255.0); + + char g[3] = { color[3], color[4], '\0' }; + diffuse.g = static_cast(strtol(g, nullptr, 16)) / ai_real(255.0); + + char b[3] = { color[5], color[6], '\0' }; + diffuse.b = static_cast(strtol(b, nullptr, 16)) / ai_real(255.0); + const size_t len = strlen(color); + if (ColRGB_Len == len) { + return true; + } + + char a[3] = { color[7], color[8], '\0' }; + diffuse.a = static_cast(strtol(a, nullptr, 16)) / ai_real(255.0); + + return true; +} + +void assignDiffuseColor(XmlNode &node, aiMaterial *mat) { + const char *color = node.attribute(XmlTag::basematerials_displaycolor).as_string(); + aiColor4D diffuse; + if (parseColor(color, diffuse)) { + mat->AddProperty(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE); + } +} + +} // namespace + +XmlSerializer::XmlSerializer(XmlParser *xmlParser) : + mResourcesDictionnary(), + mMeshCount(0), + mXmlParser(xmlParser) { + ai_assert(nullptr != xmlParser); +} + +XmlSerializer::~XmlSerializer() { + for (auto &it : mResourcesDictionnary) { + delete it.second; + } +} + +void XmlSerializer::ImportXml(aiScene *scene) { + if (nullptr == scene) { + return; + } + + scene->mRootNode = new aiNode(XmlTag::RootTag); + XmlNode node = mXmlParser->getRootNode().child(XmlTag::model); + if (node.empty()) { + return; + } + + XmlNode resNode = node.child(XmlTag::resources); + for (auto ¤tNode : resNode.children()) { + const std::string currentNodeName = currentNode.name(); + if (currentNodeName == XmlTag::texture_2d) { + ReadEmbeddecTexture(currentNode); + } else if (currentNodeName == XmlTag::texture_group) { + ReadTextureGroup(currentNode); + } else if (currentNodeName == XmlTag::object) { + ReadObject(currentNode); + } else if (currentNodeName == XmlTag::basematerials) { + ReadBaseMaterials(currentNode); + } else if (currentNodeName == XmlTag::meta) { + ReadMetadata(currentNode); + } + } + StoreMaterialsInScene(scene); + XmlNode buildNode = node.child(XmlTag::build); + if (buildNode.empty()) { + return; + } + + for (auto ¤tNode : buildNode.children()) { + const std::string currentNodeName = currentNode.name(); + if (currentNodeName == XmlTag::item) { + int objectId = IdNotSet; + std::string transformationMatrixStr; + aiMatrix4x4 transformationMatrix; + getNodeAttribute(currentNode, D3MF::XmlTag::objectid, objectId); + bool hasTransform = getNodeAttribute(currentNode, D3MF::XmlTag::transform, transformationMatrixStr); + + auto it = mResourcesDictionnary.find(objectId); + if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) { + Object *obj = static_cast(it->second); + if (hasTransform) { + transformationMatrix = parseTransformMatrix(transformationMatrixStr); + } + + addObjectToNode(scene->mRootNode, obj, transformationMatrix); + } + } + } + + // import the metadata + if (!mMetaData.empty()) { + const size_t numMeta = mMetaData.size(); + scene->mMetaData = aiMetadata::Alloc(static_cast(numMeta)); + for (size_t i = 0; i < numMeta; ++i) { + aiString val(mMetaData[i].value); + scene->mMetaData->Set(static_cast(i), mMetaData[i].name, val); + } + } + + // import the meshes, materials are already stored + scene->mNumMeshes = static_cast(mMeshCount); + if (scene->mNumMeshes != 0) { + scene->mMeshes = new aiMesh *[scene->mNumMeshes](); + for (auto &it : mResourcesDictionnary) { + if (it.second->getType() == ResourceType::RT_Object) { + Object *obj = static_cast(it.second); + ai_assert(nullptr != obj); + for (unsigned int i = 0; i < obj->mMeshes.size(); ++i) { + scene->mMeshes[obj->mMeshIndex[i]] = obj->mMeshes[i]; + } + } + } + } +} + +void XmlSerializer::addObjectToNode(aiNode *parent, Object *obj, aiMatrix4x4 nodeTransform) { + ai_assert(nullptr != obj); + + aiNode *sceneNode = new aiNode(obj->mName); + sceneNode->mNumMeshes = static_cast(obj->mMeshes.size()); + sceneNode->mMeshes = new unsigned int[sceneNode->mNumMeshes]; + std::copy(obj->mMeshIndex.begin(), obj->mMeshIndex.end(), sceneNode->mMeshes); + + sceneNode->mTransformation = nodeTransform; + if (nullptr != parent) { + parent->addChildren(1, &sceneNode); + } + + for (Assimp::D3MF::Component c : obj->mComponents) { + auto it = mResourcesDictionnary.find(c.mObjectId); + if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) { + addObjectToNode(sceneNode, static_cast(it->second), c.mTransformation); + } + } +} + +void XmlSerializer::ReadObject(XmlNode &node) { + int id = IdNotSet, pid = IdNotSet, pindex = IdNotSet; + bool hasId = getNodeAttribute(node, XmlTag::id, id); + if (!hasId) { + return; + } + + bool hasPid = getNodeAttribute(node, XmlTag::pid, pid); + bool hasPindex = getNodeAttribute(node, XmlTag::pindex, pindex); + + Object *obj = new Object(id); + for (XmlNode ¤tNode : node.children()) { + const std::string currentName = currentNode.name(); + if (currentName == D3MF::XmlTag::mesh) { + auto mesh = ReadMesh(currentNode); + mesh->mName.Set(ai_to_string(id)); + + if (hasPid) { + auto it = mResourcesDictionnary.find(pid); + if (hasPindex && it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_BaseMaterials) { + BaseMaterials *materials = static_cast(it->second); + mesh->mMaterialIndex = materials->mMaterialIndex[pindex]; + } + } + + obj->mMeshes.push_back(mesh); + obj->mMeshIndex.push_back(mMeshCount); + mMeshCount++; + } else if (currentName == D3MF::XmlTag::components) { + for (XmlNode ¤tSubNode : currentNode.children()) { + const std::string subNodeName = currentSubNode.name(); + if (subNodeName == D3MF::XmlTag::component) { + int objectId = IdNotSet; + std::string componentTransformStr; + aiMatrix4x4 componentTransform; + if (getNodeAttribute(currentSubNode, D3MF::XmlTag::transform, componentTransformStr)) { + componentTransform = parseTransformMatrix(componentTransformStr); + } + + if (getNodeAttribute(currentSubNode, D3MF::XmlTag::objectid, objectId)) { + obj->mComponents.push_back({ objectId, componentTransform }); + } + } + } + } + } + + mResourcesDictionnary.insert(std::make_pair(id, obj)); +} + +aiMesh *XmlSerializer::ReadMesh(XmlNode &node) { + if (node.empty()) { + return nullptr; + } + + aiMesh *mesh = new aiMesh(); + for (XmlNode ¤tNode : node.children()) { + const std::string currentName = currentNode.name(); + if (currentName == XmlTag::vertices) { + ImportVertices(currentNode, mesh); + } else if (currentName == XmlTag::triangles) { + ImportTriangles(currentNode, mesh); + } + } + + return mesh; +} + +void XmlSerializer::ReadMetadata(XmlNode &node) { + pugi::xml_attribute attribute = node.attribute(D3MF::XmlTag::meta_name); + const std::string name = attribute.as_string(); + const std::string value = node.value(); + if (name.empty()) { + return; + } + + MetaEntry entry; + entry.name = name; + entry.value = value; + mMetaData.push_back(entry); +} + +void XmlSerializer::ImportVertices(XmlNode &node, aiMesh *mesh) { + ai_assert(nullptr != mesh); + + std::vector vertices; + for (XmlNode ¤tNode : node.children()) { + const std::string currentName = currentNode.name(); + if (currentName == XmlTag::vertex) { + vertices.push_back(ReadVertex(currentNode)); + } + } + + mesh->mNumVertices = static_cast(vertices.size()); + mesh->mVertices = new aiVector3D[mesh->mNumVertices]; + std::copy(vertices.begin(), vertices.end(), mesh->mVertices); +} + +void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) { + std::vector faces; + for (XmlNode ¤tNode : node.children()) { + const std::string currentName = currentNode.name(); + if (currentName == XmlTag::triangle) { + int pid = IdNotSet, p1 = IdNotSet; + bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid); + bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1); + + if (hasPid && hasP1) { + auto it = mResourcesDictionnary.find(pid); + if (it != mResourcesDictionnary.end()) { + if (it->second->getType() == ResourceType::RT_BaseMaterials) { + BaseMaterials *baseMaterials = static_cast(it->second); + mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1]; + } else if (it->second->getType() == ResourceType::RT_Texture2DGroup) { + if (mesh->mTextureCoords[0] == nullptr) { + Texture2DGroup *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); + } + } + } + } + } + + aiFace face = ReadTriangle(currentNode); + faces.push_back(face); + } + } + + mesh->mNumFaces = static_cast(faces.size()); + mesh->mFaces = new aiFace[mesh->mNumFaces]; + mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; + + std::copy(faces.begin(), faces.end(), mesh->mFaces); +} + +void XmlSerializer::ReadBaseMaterials(XmlNode &node) { + int id = IdNotSet; + if (getNodeAttribute(node, D3MF::XmlTag::id, id)) { + BaseMaterials *baseMaterials = new BaseMaterials(id); + + for (XmlNode ¤tNode : node.children()) { + const std::string currentName = currentNode.name(); + if (currentName == XmlTag::basematerials_base) { + baseMaterials->mMaterialIndex.push_back(static_cast(mMaterials.size())); + mMaterials.push_back(readMaterialDef(currentNode, id)); + } + } + + mResourcesDictionnary.insert(std::make_pair(id, baseMaterials)); + } +} + +void XmlSerializer::ReadEmbeddecTexture(XmlNode &node) { + if (node.empty()) { + return; + } + + std::string value; + EmbeddedTexture *tex2D = nullptr; + if (XmlParser::getStdStrAttribute(node, XmlTag::id, value)) { + tex2D = new EmbeddedTexture(atoi(value.c_str())); + } + if (nullptr == tex2D) { + return; + } + + if (XmlParser::getStdStrAttribute(node, XmlTag::path, value)) { + tex2D->mPath = value; + } + if (XmlParser::getStdStrAttribute(node, XmlTag::texture_content_type, value)) { + tex2D->mContentType = value; + } + if (XmlParser::getStdStrAttribute(node, XmlTag::texture_tilestyleu, value)) { + tex2D->mTilestyleU = value; + } + if (XmlParser::getStdStrAttribute(node, XmlTag::texture_tilestylev, value)) { + tex2D->mTilestyleV = value; + } + mEmbeddedTextures.emplace_back(tex2D); + StoreEmbeddedTexture(tex2D); +} + +void XmlSerializer::StoreEmbeddedTexture(EmbeddedTexture *tex) { + aiMaterial *mat = new aiMaterial; + aiString s; + s.Set(ai_to_string(tex->mId).c_str()); + mat->AddProperty(&s, AI_MATKEY_NAME); + const std::string name = "*" + tex->mPath; + s.Set(name); + mat->AddProperty(&s, AI_MATKEY_TEXTURE_DIFFUSE(0)); + + aiColor3D col; + mat->AddProperty(&col, 1, AI_MATKEY_COLOR_DIFFUSE); + mat->AddProperty(&col, 1, AI_MATKEY_COLOR_AMBIENT); + mat->AddProperty(&col, 1, AI_MATKEY_COLOR_EMISSIVE); + mat->AddProperty(&col, 1, AI_MATKEY_COLOR_SPECULAR); + mMaterials.emplace_back(mat); +} + +void XmlSerializer::ReadTextureCoords2D(XmlNode &node, Texture2DGroup *tex2DGroup) { + if (node.empty() || nullptr == tex2DGroup) { + return; + } + + int id = IdNotSet; + if (XmlParser::getIntAttribute(node, "texid", id)) { + tex2DGroup->mTexId = id; + } + + double value = 0.0; + for (XmlNode currentNode : node.children()) { + const std::string currentName = currentNode.name(); + aiVector2D texCoord; + if (currentName == XmlTag::texture_2d_coord) { + XmlParser::getDoubleAttribute(currentNode, XmlTag::texture_cuurd_u, value); + texCoord.x = (ai_real)value; + XmlParser::getDoubleAttribute(currentNode, XmlTag::texture_cuurd_v, value); + texCoord.y = (ai_real)value; + tex2DGroup->mTex2dCoords.push_back(texCoord); + } + } +} + +void XmlSerializer::ReadTextureGroup(XmlNode &node) { + if (node.empty()) { + return; + } + + int id = IdNotSet; + if (!XmlParser::getIntAttribute(node, XmlTag::id, id)) { + return; + } + + Texture2DGroup *group = new Texture2DGroup(id); + ReadTextureCoords2D(node, group); + mResourcesDictionnary.insert(std::make_pair(id, group)); +} + +aiMaterial *XmlSerializer::readMaterialDef(XmlNode &node, unsigned int basematerialsId) { + aiMaterial *material = new aiMaterial(); + material->mNumProperties = 0; + std::string name; + bool hasName = getNodeAttribute(node, D3MF::XmlTag::basematerials_name, name); + + std::string stdMaterialName; + const std::string strId(ai_to_string(basematerialsId)); + stdMaterialName += "id"; + stdMaterialName += strId; + stdMaterialName += "_"; + if (hasName) { + stdMaterialName += std::string(name); + } else { + stdMaterialName += "basemat_"; + stdMaterialName += ai_to_string(mMaterials.size()); + } + + aiString assimpMaterialName(stdMaterialName); + material->AddProperty(&assimpMaterialName, AI_MATKEY_NAME); + + assignDiffuseColor(node, material); + + return material; +} + +void XmlSerializer::StoreMaterialsInScene(aiScene *scene) { + if (nullptr == scene || mMaterials.empty()) { + return; + } + + scene->mNumMaterials = static_cast(mMaterials.size()); + scene->mMaterials = new aiMaterial *[scene->mNumMaterials]; + for (size_t i = 0; i < mMaterials.size(); ++i) { + scene->mMaterials[i] = mMaterials[i]; + } +} + +} // namespace D3MF +} // namespace Assimp diff --git a/include/assimp/Defines.h b/code/AssetLib/3MF/XmlSerializer.h similarity index 53% rename from include/assimp/Defines.h rename to code/AssetLib/3MF/XmlSerializer.h index a756b2864..14da82e99 100644 --- a/include/assimp/Defines.h +++ b/code/AssetLib/3MF/XmlSerializer.h @@ -3,6 +3,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- Copyright (c) 2006-2021, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -37,22 +38,59 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ - #pragma once -#ifndef AI_DEFINES_H_INC -#define AI_DEFINES_H_INC -#ifdef __GNUC__ -# pragma GCC system_header -#endif +#include +#include +#include +#include -// We need those constants, workaround for any platforms where nobody defined them yet -#if (!defined SIZE_MAX) -# define SIZE_MAX (~((size_t)0)) -#endif +struct aiNode; +struct aiMesh; +struct aiMaterial; -#if (!defined UINT_MAX) -# define UINT_MAX (~((unsigned int)0)) -#endif +namespace Assimp { +namespace D3MF { -#endif // AI_DEINES_H_INC +class Resource; +class D3MFOpcPackage; +class Object; +class Texture2DGroup; +class EmbeddedTexture; + +class XmlSerializer { +public: + XmlSerializer(XmlParser *xmlParser); + ~XmlSerializer(); + void ImportXml(aiScene *scene); + +private: + void addObjectToNode(aiNode *parent, Object *obj, aiMatrix4x4 nodeTransform); + void ReadObject(XmlNode &node); + aiMesh *ReadMesh(XmlNode &node); + void ReadMetadata(XmlNode &node); + void ImportVertices(XmlNode &node, aiMesh *mesh); + void ImportTriangles(XmlNode &node, aiMesh *mesh); + void ReadBaseMaterials(XmlNode &node); + void ReadEmbeddecTexture(XmlNode &node); + void StoreEmbeddedTexture(EmbeddedTexture *tex); + void ReadTextureCoords2D(XmlNode &node, Texture2DGroup *tex2DGroup); + void ReadTextureGroup(XmlNode &node); + aiMaterial *readMaterialDef(XmlNode &node, unsigned int basematerialsId); + void StoreMaterialsInScene(aiScene *scene); + +private: + struct MetaEntry { + std::string name; + std::string value; + }; + std::vector mMetaData; + std::vector mEmbeddedTextures; + std::vector mMaterials; + std::map mResourcesDictionnary; + unsigned int mMeshCount; + XmlParser *mXmlParser; +}; + +} // namespace D3MF +} // namespace Assimp diff --git a/code/AssetLib/AC/ACLoader.h b/code/AssetLib/AC/ACLoader.h index 5ae2e80bb..5b706a4a0 100644 --- a/code/AssetLib/AC/ACLoader.h +++ b/code/AssetLib/AC/ACLoader.h @@ -63,7 +63,7 @@ namespace Assimp { class AC3DImporter : public BaseImporter { public: AC3DImporter(); - ~AC3DImporter(); + ~AC3DImporter() override; // Represents an AC3D material struct Material { @@ -185,25 +185,25 @@ public: * See BaseImporter::CanRead() for details. */ bool CanRead(const std::string &pFile, IOSystem *pIOHandler, - bool checkSig) const; + bool checkSig) const override; protected: // ------------------------------------------------------------------- /** Return importer meta information. * See #BaseImporter::GetInfo for the details */ - const aiImporterDesc *GetInfo() const; + const aiImporterDesc *GetInfo() const override; // ------------------------------------------------------------------- /** Imports the given file into the given scene structure. * See BaseImporter::InternReadFile() for details*/ void InternReadFile(const std::string &pFile, aiScene *pScene, - IOSystem *pIOHandler); + IOSystem *pIOHandler) override; // ------------------------------------------------------------------- /** Called prior to ReadFile(). * The function is a request to the importer to update its configuration * basing on the Importer's configuration property list.*/ - void SetupProperties(const Importer *pImp); + void SetupProperties(const Importer *pImp) override; private: // ------------------------------------------------------------------- diff --git a/code/AssetLib/AMF/AMFImporter.cpp b/code/AssetLib/AMF/AMFImporter.cpp index 615882b6a..9a9ab94ca 100644 --- a/code/AssetLib/AMF/AMFImporter.cpp +++ b/code/AssetLib/AMF/AMFImporter.cpp @@ -303,7 +303,7 @@ void AMFImporter::ParseNode_Root() { } XmlNode node = *root; mUnit = ai_tolower(std::string(node.attribute("unit").as_string())); - + mVersion = node.attribute("version").as_string(); // Read attributes for node . @@ -511,7 +511,7 @@ bool AMFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool p } if (extension.empty() || pCheckSig) { - const char *tokens[] = { "Child.push_back(ne); @@ -199,9 +199,9 @@ void AMFImporter::ParseNode_Volume(XmlNode &node) { // Read attributes for node . // and assign read data - + ((AMFVolume *)ne)->MaterialID = node.attribute("materialid").as_string(); - + ((AMFVolume *)ne)->Type = type; // Check for child nodes bool col_read = false; diff --git a/code/AssetLib/AMF/AMFImporter_Node.hpp b/code/AssetLib/AMF/AMFImporter_Node.hpp index 9051b2871..b466e339b 100644 --- a/code/AssetLib/AMF/AMFImporter_Node.hpp +++ b/code/AssetLib/AMF/AMFImporter_Node.hpp @@ -48,15 +48,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef INCLUDED_AI_AMF_IMPORTER_NODE_H #define INCLUDED_AI_AMF_IMPORTER_NODE_H -// Header files, stdlib. +// Header files, Assimp. +#include +#include + #include #include #include -// Header files, Assimp. -#include "assimp/scene.h" -#include "assimp/types.h" - /// \class CAMFImporter_NodeElement /// Base class for elements of nodes. class AMFNodeElementBase { diff --git a/code/AssetLib/AMF/AMFImporter_Postprocess.cpp b/code/AssetLib/AMF/AMFImporter_Postprocess.cpp index 43d0de52f..3674f3d25 100644 --- a/code/AssetLib/AMF/AMFImporter_Postprocess.cpp +++ b/code/AssetLib/AMF/AMFImporter_Postprocess.cpp @@ -69,7 +69,7 @@ aiColor4D AMFImporter::SPP_Material::GetColor(const float /*pX*/, const float /* } tcol = Color->Color; - + // Check if default color must be used if ((tcol.r == 0) && (tcol.g == 0) && (tcol.b == 0) && (tcol.a == 0)) { tcol.r = 0.5f; @@ -99,10 +99,10 @@ void AMFImporter::PostprocessHelper_CreateMeshDataArray(const AMFMesh &nodeEleme } // all coordinates stored as child and we need to reserve space for future push_back's. - vertexCoordinateArray.reserve(vn->Child.size()); + vertexCoordinateArray.reserve(vn->Child.size()); // colors count equal vertices count. - pVertexColorArray.resize(vn->Child.size()); + pVertexColorArray.resize(vn->Child.size()); col_idx = 0; // Inside vertices collect all data and place to arrays @@ -690,7 +690,7 @@ void AMFImporter::Postprocess_BuildConstellation(AMFConstellation &pConstellatio if (ne->Type == AMFNodeElementBase::ENET_Metadata) continue; if (ne->Type != AMFNodeElementBase::ENET_Instance) throw DeadlyImportError("Only nodes can be in ."); - // create alias for conveniance + // create alias for convenience AMFInstance &als = *((AMFInstance *)ne); // find referenced object if (!Find_ConvertedNode(als.ObjectID, nodeArray, &found_node)) Throw_ID_NotFound(als.ObjectID); diff --git a/code/AssetLib/ASE/ASELoader.cpp b/code/AssetLib/ASE/ASELoader.cpp index 1a42c2f52..fae441f57 100644 --- a/code/AssetLib/ASE/ASELoader.cpp +++ b/code/AssetLib/ASE/ASELoader.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2021, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -106,7 +104,7 @@ bool ASEImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c } if ((!extension.length() || cs) && pIOHandler) { - const char *tokens[] = { "*3dsmax_asciiexport" }; + static const char * const tokens[] = { "*3dsmax_asciiexport" }; return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1); } return false; @@ -683,7 +681,7 @@ void ASEImporter::BuildNodes(std::vector &nodes) { } } - // Are there ane orphaned nodes? + // Are there any orphaned nodes? if (!aiList.empty()) { std::vector apcNodes; apcNodes.reserve(aiList.size() + pcScene->mRootNode->mNumChildren); diff --git a/code/AssetLib/ASE/ASELoader.h b/code/AssetLib/ASE/ASELoader.h index 1f30d28e7..9ec9d439f 100644 --- a/code/AssetLib/ASE/ASELoader.h +++ b/code/AssetLib/ASE/ASELoader.h @@ -62,42 +62,37 @@ namespace Assimp { class ASEImporter : public BaseImporter { public: ASEImporter(); - ~ASEImporter(); + ~ASEImporter() override; // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. * See BaseImporter::CanRead() for details. */ bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; + bool checkSig) const override; protected: - // ------------------------------------------------------------------- /** Return importer meta information. * See #BaseImporter::GetInfo for the details */ - const aiImporterDesc* GetInfo () const; - + const aiImporterDesc* GetInfo () const override; // ------------------------------------------------------------------- /** Imports the given file into the given scene structure. * See BaseImporter::InternReadFile() for details */ void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - + IOSystem* pIOHandler) override; // ------------------------------------------------------------------- /** Called prior to ReadFile(). * The function is a request to the importer to update its configuration * basing on the Importer's configuration property list. */ - void SetupProperties(const Importer* pImp); - + void SetupProperties(const Importer* pImp) override; private: - // ------------------------------------------------------------------- /** Generate normal vectors basing on smoothing groups * (in some cases the normal are already contained in the file) @@ -106,7 +101,6 @@ private: */ bool GenerateNormals(ASE::Mesh& mesh); - // ------------------------------------------------------------------- /** Create valid vertex/normal/UV/color/face lists. * All elements are unique, faces have only one set of indices @@ -115,51 +109,43 @@ private: */ void BuildUniqueRepresentation(ASE::Mesh& mesh); - /** Create one-material-per-mesh meshes ;-) * \param mesh Mesh to work with * \param Receives the list of all created meshes */ void ConvertMeshes(ASE::Mesh& mesh, std::vector& avOut); - // ------------------------------------------------------------------- /** Convert a material to a aiMaterial object * \param mat Input material */ void ConvertMaterial(ASE::Material& mat); - // ------------------------------------------------------------------- /** Setup the final material indices for each mesh */ void BuildMaterialIndices(); - // ------------------------------------------------------------------- /** Build the node graph */ void BuildNodes(std::vector& nodes); - // ------------------------------------------------------------------- /** Build output cameras */ void BuildCameras(); - // ------------------------------------------------------------------- /** Build output lights */ void BuildLights(); - // ------------------------------------------------------------------- /** Build output animations */ void BuildAnimations(const std::vector& nodes); - // ------------------------------------------------------------------- /** Add sub nodes to a node * \param pcParent parent node to be filled @@ -183,7 +169,6 @@ private: void GenerateDefaultMaterial(); protected: - /** Parser instance */ ASE::Parser* mParser; diff --git a/code/AssetLib/ASE/ASEParser.cpp b/code/AssetLib/ASE/ASEParser.cpp index 1f7018b11..a2884b8dd 100644 --- a/code/AssetLib/ASE/ASEParser.cpp +++ b/code/AssetLib/ASE/ASEParser.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2021, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/AssetLib/ASE/ASEParser.h b/code/AssetLib/ASE/ASEParser.h index d04fc0662..f49cfc36f 100644 --- a/code/AssetLib/ASE/ASEParser.h +++ b/code/AssetLib/ASE/ASEParser.h @@ -95,8 +95,8 @@ struct Material : public D3DS::Material { Material(Material &&other) AI_NO_EXCEPT : D3DS::Material(std::move(other)), avSubMaterials(std::move(other.avSubMaterials)), - pcInstance(std::move(other.pcInstance)), - bNeed(std::move(other.bNeed)) { + pcInstance(other.pcInstance), + bNeed(other.bNeed) { other.pcInstance = nullptr; } @@ -108,8 +108,8 @@ struct Material : public D3DS::Material { //D3DS::Material::operator=(std::move(other)); avSubMaterials = std::move(other.avSubMaterials); - pcInstance = std::move(other.pcInstance); - bNeed = std::move(other.bNeed); + pcInstance = other.pcInstance; + bNeed = other.bNeed; other.pcInstance = nullptr; diff --git a/code/AssetLib/Assbin/AssbinExporter.h b/code/AssetLib/Assbin/AssbinExporter.h index 96dfdd1c2..b6f2acd3d 100644 --- a/code/AssetLib/Assbin/AssbinExporter.h +++ b/code/AssetLib/Assbin/AssbinExporter.h @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2021, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -43,16 +42,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file AssbinExporter.h * ASSBIN Exporter Main Header */ +#pragma once #ifndef AI_ASSBINEXPORTER_H_INC #define AI_ASSBINEXPORTER_H_INC #include +#ifndef ASSIMP_BUILD_NO_EXPORT + // nothing really needed here - reserved for future use like properties namespace Assimp { void ASSIMP_API ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/); } - +#endif #endif // AI_ASSBINEXPORTER_H_INC diff --git a/code/AssetLib/Assbin/AssbinFileWriter.cpp b/code/AssetLib/Assbin/AssbinFileWriter.cpp index 95379a303..21bfd8512 100644 --- a/code/AssetLib/Assbin/AssbinFileWriter.cpp +++ b/code/AssetLib/Assbin/AssbinFileWriter.cpp @@ -43,13 +43,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "AssbinFileWriter.h" - #include "Common/assbin_chunks.h" #include "PostProcessing/ProcessHelper.h" #include #include -#include #include #ifdef ASSIMP_BUILD_NO_OWN_ZLIB @@ -58,7 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../contrib/zlib/zlib.h" #endif -#include +#include #if _MSC_VER #pragma warning(push) @@ -172,7 +170,7 @@ inline size_t Write(IOStream *stream, const aiQuaternion &v) { t += Write(stream, v.z); ai_assert(t == 16); - return 16; + return t; } // ----------------------------------------------------------------------------------- @@ -277,7 +275,7 @@ public: // empty } - virtual ~AssbinChunkWriter() { + ~AssbinChunkWriter() override { if (container) { container->Write(&magic, sizeof(uint32_t), 1); container->Write(&cursor, sizeof(uint32_t), 1); @@ -288,26 +286,27 @@ public: void *GetBufferPointer() { return buffer; } - // ------------------------------------------------------------------- - virtual size_t Read(void * /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) { + size_t Read(void * /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) override { return 0; } - virtual aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) { + + aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) override { return aiReturn_FAILURE; } - virtual size_t Tell() const { + + size_t Tell() const override { return cursor; } - virtual void Flush() { + + void Flush() override { // not implemented } - virtual size_t FileSize() const { + size_t FileSize() const override { return cursor; } - // ------------------------------------------------------------------- - virtual size_t Write(const void *pvBuffer, size_t pSize, size_t pCount) { + size_t Write(const void *pvBuffer, size_t pSize, size_t pCount) override { pSize *= pCount; if (cursor + pSize > cur_size) { Grow(cursor + pSize); diff --git a/code/AssetLib/Assbin/AssbinLoader.cpp b/code/AssetLib/Assbin/AssbinLoader.cpp index d94407e03..5ca4b3e11 100644 --- a/code/AssetLib/Assbin/AssbinLoader.cpp +++ b/code/AssetLib/Assbin/AssbinLoader.cpp @@ -406,7 +406,7 @@ void AssbinImporter::ReadBinaryMesh(IOStream *stream, aiMesh *mesh) { f.mIndices = new unsigned int[f.mNumIndices]; for (unsigned int a = 0; a < f.mNumIndices; ++a) { - // Check if unsigned short ( 16 bit ) are big enought for the indices + // Check if unsigned short ( 16 bit ) are big enough for the indices if (fitsIntoUI16(mesh->mNumVertices)) { f.mIndices[a] = Read(stream); } else { diff --git a/code/AssetLib/Assbin/AssbinLoader.h b/code/AssetLib/Assbin/AssbinLoader.h index 59d799a3d..47f38db2a 100644 --- a/code/AssetLib/Assbin/AssbinLoader.h +++ b/code/AssetLib/Assbin/AssbinLoader.h @@ -5,7 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2021, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -74,17 +73,11 @@ private: bool compressed; public: - virtual bool CanRead( - const std::string& pFile, - IOSystem* pIOHandler, - bool checkSig - ) const; - virtual const aiImporterDesc* GetInfo() const; - virtual void InternReadFile( - const std::string& pFile, - aiScene* pScene, - IOSystem* pIOHandler - ); + bool CanRead(const std::string& pFile, + IOSystem* pIOHandler, bool checkSig) const override; + const aiImporterDesc* GetInfo() const override; + void InternReadFile( + const std::string& pFile,aiScene* pScene,IOSystem* pIOHandler) override; void ReadHeader(); void ReadBinaryScene( IOStream * stream, aiScene* pScene ); void ReadBinaryNode( IOStream * stream, aiNode** mRootNode, aiNode* parent ); diff --git a/code/AssetLib/Assjson/json_exporter.cpp b/code/AssetLib/Assjson/json_exporter.cpp index b9099d392..7b2c8ec81 100644 --- a/code/AssetLib/Assjson/json_exporter.cpp +++ b/code/AssetLib/Assjson/json_exporter.cpp @@ -41,12 +41,17 @@ public: enum { Flag_DoNotIndent = 0x1, Flag_WriteSpecialFloats = 0x2, + Flag_SkipWhitespaces = 0x4 }; - + JSONWriter(Assimp::IOStream &out, unsigned int flags = 0u) : - out(out), first(), flags(flags) { + out(out), indent (""), newline("\n"), space(" "), buff (), first(false), flags(flags) { // make sure that all formatting happens using the standard, C locale and not the user's current locale buff.imbue(std::locale("C")); + if (flags & Flag_SkipWhitespaces) { + newline = ""; + space = ""; + } } ~JSONWriter() { @@ -70,7 +75,7 @@ public: void Key(const std::string &name) { AddIndentation(); Delimit(); - buff << '\"' + name + "\": "; + buff << '\"' + name + "\":" << space; } template @@ -78,12 +83,12 @@ public: AddIndentation(); Delimit(); - LiteralToString(buff, name) << '\n'; + LiteralToString(buff, name) << newline; } template void SimpleValue(const Literal &s) { - LiteralToString(buff, s) << '\n'; + LiteralToString(buff, s) << newline; } void SimpleValue(const void *buffer, size_t len) { @@ -102,7 +107,7 @@ public: } } - buff << '\"' << cur_out << "\"\n"; + buff << '\"' << cur_out << "\"" << newline; delete[] cur_out; } @@ -115,7 +120,7 @@ public: } } first = true; - buff << "{\n"; + buff << "{" << newline; PushIndent(); } @@ -123,7 +128,7 @@ public: PopIndent(); AddIndentation(); first = false; - buff << "}\n"; + buff << "}" << newline; } void StartArray(bool is_element = false) { @@ -135,19 +140,19 @@ public: } } first = true; - buff << "[\n"; + buff << "[" << newline; PushIndent(); } void EndArray() { PopIndent(); AddIndentation(); - buff << "]\n"; + buff << "]" << newline; first = false; } void AddIndentation() { - if (!(flags & Flag_DoNotIndent)) { + if (!(flags & Flag_DoNotIndent) && !(flags & Flag_SkipWhitespaces)) { buff << indent; } } @@ -156,7 +161,7 @@ public: if (!first) { buff << ','; } else { - buff << ' '; + buff << space; first = false; } } @@ -227,7 +232,9 @@ private: private: Assimp::IOStream &out; - std::string indent, newline; + std::string indent; + std::string newline; + std::string space; std::stringstream buff; bool first; @@ -765,7 +772,7 @@ void Write(JSONWriter &out, const aiScene &ai) { out.EndObj(); } -void ExportAssimp2Json(const char *file, Assimp::IOSystem *io, const aiScene *scene, const Assimp::ExportProperties *) { +void ExportAssimp2Json(const char *file, Assimp::IOSystem *io, const aiScene *scene, const Assimp::ExportProperties *pProperties) { std::unique_ptr str(io->Open(file, "wt")); if (!str) { throw DeadlyExportError("could not open output file"); @@ -782,7 +789,12 @@ void ExportAssimp2Json(const char *file, Assimp::IOSystem *io, const aiScene *sc splitter.Execute(scenecopy_tmp); // XXX Flag_WriteSpecialFloats is turned on by default, right now we don't have a configuration interface for exporters - JSONWriter s(*str, JSONWriter::Flag_WriteSpecialFloats); + + unsigned int flags = JSONWriter::Flag_WriteSpecialFloats; + if (pProperties->GetPropertyBool("JSON_SKIP_WHITESPACES", false)) { + flags |= JSONWriter::Flag_SkipWhitespaces; + } + JSONWriter s(*str, flags); Write(s, *scenecopy_tmp); } catch (...) { diff --git a/code/AssetLib/Assjson/mesh_splitter.cpp b/code/AssetLib/Assjson/mesh_splitter.cpp index 24385f9a0..978437c41 100644 --- a/code/AssetLib/Assjson/mesh_splitter.cpp +++ b/code/AssetLib/Assjson/mesh_splitter.cpp @@ -69,13 +69,12 @@ void MeshSplitter::UpdateNode(aiNode* pcNode, const std::vectormNumChildren; i < end;++i) { UpdateNode ( pcNode->mChildren[i], source_mesh_map ); } - return; } -#define WAS_NOT_COPIED 0xffffffff +static const unsigned int WAS_NOT_COPIED = 0xffffffff; -typedef std::pair PerVertexWeight; -typedef std::vector VertexWeightTable; +using PerVertexWeight = std::pair ; +using VertexWeightTable = std::vector ; // ------------------------------------------------------------------------------------------------ VertexWeightTable* ComputeVertexBoneWeightTable(const aiMesh* pMesh) { @@ -89,7 +88,7 @@ VertexWeightTable* ComputeVertexBoneWeightTable(const aiMesh* pMesh) { aiBone* bone = pMesh->mBones[i]; for (unsigned int a = 0; a < bone->mNumWeights;++a) { const aiVertexWeight& weight = bone->mWeights[a]; - avPerVertexWeights[weight.mVertexId].push_back( std::make_pair(i,weight.mWeight) ); + avPerVertexWeights[weight.mVertexId].emplace_back(i,weight.mWeight); } } return avPerVertexWeights; @@ -100,7 +99,7 @@ void MeshSplitter :: SplitMesh(unsigned int a, aiMesh* in_mesh, std::vectormNumVertices <= LIMIT) { - source_mesh_map.push_back(std::make_pair(in_mesh,a)); + source_mesh_map.emplace_back(in_mesh,a); return; } @@ -110,7 +109,7 @@ void MeshSplitter :: SplitMesh(unsigned int a, aiMesh* in_mesh, std::vectormNumVertices / LIMIT) + 1; - // create a std::vector to remember which vertices have already + // create a std::vector to remember which vertices have already // been copied and to which position (i.e. output index) std::vector was_copied_to; was_copied_to.resize(in_mesh->mNumVertices,WAS_NOT_COPIED); @@ -125,7 +124,7 @@ void MeshSplitter :: SplitMesh(unsigned int a, aiMesh* in_mesh, std::vectormNumVertices = 0; out_mesh->mMaterialIndex = in_mesh->mMaterialIndex; @@ -179,7 +178,7 @@ void MeshSplitter :: SplitMesh(unsigned int a, aiMesh* in_mesh, std::vectormNumVertices + iNeed > out_vertex_index) { @@ -187,7 +186,7 @@ void MeshSplitter :: SplitMesh(unsigned int a, aiMesh* in_mesh, std::vectormTextureCoords[c][out_mesh->mNumVertices] = in_mesh->mTextureCoords[c][index]; } } - // vertex colors + // vertex colors for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) { if (in_mesh->HasVertexColors( c)) { out_mesh->mColors[c][out_mesh->mNumVertices] = in_mesh->mColors[c][index]; diff --git a/code/AssetLib/Assjson/mesh_splitter.h b/code/AssetLib/Assjson/mesh_splitter.h index 326f73b41..f7f9a9326 100644 --- a/code/AssetLib/Assjson/mesh_splitter.h +++ b/code/AssetLib/Assjson/mesh_splitter.h @@ -22,40 +22,31 @@ struct aiNode; // --------------------------------------------------------------------------- /** Splits meshes of unique vertices into meshes with no more vertices than - * a given, configurable threshold value. + * a given, configurable threshold value. */ -class MeshSplitter -{ - +class MeshSplitter { public: - - void SetLimit(unsigned int l) { - LIMIT = l; - } + unsigned int LIMIT; - unsigned int GetLimit() const { - return LIMIT; - } + void SetLimit(unsigned int l) { + LIMIT = l; + } -public: + unsigned int GetLimit() const { + return LIMIT; + } - // ------------------------------------------------------------------- - /** Executes the post processing step on the given imported data. + // ------------------------------------------------------------------- + /** Executes the post processing step on the given imported data. * At the moment a process is not supposed to fail. * @param pScene The imported data to work at. */ - void Execute( aiScene* pScene); - + void Execute(aiScene *pScene); private: + void UpdateNode(aiNode *pcNode, const std::vector> &source_mesh_map); + void SplitMesh(unsigned int index, aiMesh *mesh, std::vector> &source_mesh_map); - void UpdateNode(aiNode* pcNode, const std::vector >& source_mesh_map); - void SplitMesh (unsigned int index, aiMesh* mesh, std::vector >& source_mesh_map); - -public: - - unsigned int LIMIT; }; #endif // INCLUDED_MESH_SPLITTER - diff --git a/code/AssetLib/Assxml/AssxmlExporter.cpp b/code/AssetLib/Assxml/AssxmlExporter.cpp index 847ba0d7e..d244813b1 100644 --- a/code/AssetLib/Assxml/AssxmlExporter.cpp +++ b/code/AssetLib/Assxml/AssxmlExporter.cpp @@ -50,7 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -namespace Assimp { +namespace Assimp { void ExportSceneAssxml(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) { diff --git a/code/AssetLib/Assxml/AssxmlExporter.h b/code/AssetLib/Assxml/AssxmlExporter.h index 5c7f155d1..9a3d1f9d5 100644 --- a/code/AssetLib/Assxml/AssxmlExporter.h +++ b/code/AssetLib/Assxml/AssxmlExporter.h @@ -43,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file AssxmlExporter.h * ASSXML Exporter Main Header */ +#pragma once #ifndef AI_ASSXMLEXPORTER_H_INC #define AI_ASSXMLEXPORTER_H_INC diff --git a/code/AssetLib/Assxml/AssxmlFileWriter.cpp b/code/AssetLib/Assxml/AssxmlFileWriter.cpp index 24fda5955..80c2db908 100644 --- a/code/AssetLib/Assxml/AssxmlFileWriter.cpp +++ b/code/AssetLib/Assxml/AssxmlFileWriter.cpp @@ -168,7 +168,7 @@ static void WriteNode(const aiNode *node, IOStream *io, unsigned int depth) { } // ----------------------------------------------------------------------------------- -// Some chuncks of text will need to be encoded for XML +// Some chunks of text will need to be encoded for XML // http://stackoverflow.com/questions/5665231/most-efficient-way-to-escape-xml-html-in-c-string#5665377 static std::string encodeXML(const std::string &data) { std::string buffer; @@ -601,7 +601,7 @@ static void WriteDump(const char *pFile, const char *cmd, const aiScene *scene, ioprintf(io, "\t\t \n", mesh->mNumVertices, a, - mesh->mTextureCoordsNames[a].C_Str(), + (mesh->HasTextureCoordsName(a) ? mesh->GetTextureCoordsName(a)->C_Str() : ""), mesh->mNumUVComponents[a]); if (!shortened) { diff --git a/code/AssetLib/Assxml/AssxmlFileWriter.h b/code/AssetLib/Assxml/AssxmlFileWriter.h index e5f27095e..125869d1a 100644 --- a/code/AssetLib/Assxml/AssxmlFileWriter.h +++ b/code/AssetLib/Assxml/AssxmlFileWriter.h @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2021, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -43,7 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file AssxmlFileWriter.h * @brief Declaration of Assxml file writer. */ - +#pragma once #ifndef AI_ASSXMLFILEWRITER_H_INC #define AI_ASSXMLFILEWRITER_H_INC diff --git a/code/AssetLib/B3D/B3DImporter.cpp b/code/AssetLib/B3D/B3DImporter.cpp index 3d9a5075a..11f7bcd14 100644 --- a/code/AssetLib/B3D/B3DImporter.cpp +++ b/code/AssetLib/B3D/B3DImporter.cpp @@ -143,7 +143,7 @@ AI_WONT_RETURN void B3DImporter::Oops() { } // ------------------------------------------------------------------------------------------------ -AI_WONT_RETURN void B3DImporter::Fail(string str) { +AI_WONT_RETURN void B3DImporter::Fail(const string &str) { #ifdef DEBUG_B3D ASSIMP_LOG_ERROR("Error in B3D file data: ", str); #endif diff --git a/code/AssetLib/B3D/B3DImporter.h b/code/AssetLib/B3D/B3DImporter.h index e2a75abdf..bb535afd1 100644 --- a/code/AssetLib/B3D/B3DImporter.h +++ b/code/AssetLib/B3D/B3DImporter.h @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2021, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -40,8 +39,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ -/** @file Definition of the .b3d importer class. */ - +/** + * @file Definition of the .b3d importer class. + */ +#pragma once #ifndef AI_B3DIMPORTER_H_INC #define AI_B3DIMPORTER_H_INC @@ -62,14 +63,12 @@ namespace Assimp{ class B3DImporter : public BaseImporter{ public: B3DImporter() = default; - virtual ~B3DImporter(); - - virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const; + ~B3DImporter() override; + bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const override; protected: - - virtual const aiImporterDesc* GetInfo () const; - virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); + const aiImporterDesc* GetInfo () const override; + void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) override; private: @@ -96,7 +95,7 @@ private: }; AI_WONT_RETURN void Oops() AI_WONT_RETURN_SUFFIX; - AI_WONT_RETURN void Fail( std::string str ) AI_WONT_RETURN_SUFFIX; + AI_WONT_RETURN void Fail(const std::string &str) AI_WONT_RETURN_SUFFIX; void ReadTEXS(); void ReadBRUS(); @@ -113,7 +112,6 @@ private: void ReadBB3D( aiScene *scene ); size_t _pos; -// unsigned _size; std::vector _buf; std::vector _stack; diff --git a/code/AssetLib/BVH/BVHLoader.cpp b/code/AssetLib/BVH/BVHLoader.cpp index cf78fb6c6..6dc824e2f 100644 --- a/code/AssetLib/BVH/BVHLoader.cpp +++ b/code/AssetLib/BVH/BVHLoader.cpp @@ -100,7 +100,7 @@ bool BVHLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool cs) return true; if ((!extension.length() || cs) && pIOHandler) { - const char *tokens[] = { "HIERARCHY" }; + static const char * const tokens[] = { "HIERARCHY" }; return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1); } return false; @@ -178,7 +178,7 @@ void BVHLoader::ReadHierarchy(aiScene *pScene) { } // ------------------------------------------------------------------------------------------------ -// Reads a node and recursively its childs and returns the created node; +// Reads a node and recursively its children and returns the created node; aiNode *BVHLoader::ReadNode() { // first token is name std::string nodeName = GetNextToken(); diff --git a/code/AssetLib/BVH/BVHLoader.h b/code/AssetLib/BVH/BVHLoader.h index a66a20275..70511483d 100644 --- a/code/AssetLib/BVH/BVHLoader.h +++ b/code/AssetLib/BVH/BVHLoader.h @@ -112,7 +112,7 @@ protected: /** Reads the hierarchy */ void ReadHierarchy(aiScene *pScene); - /** Reads a node and recursively its childs and returns the created node. */ + /** Reads a node and recursively its children and returns the created node. */ aiNode *ReadNode(); /** Reads an end node and returns the created node. */ diff --git a/code/AssetLib/Blender/BlenderDNA.h b/code/AssetLib/Blender/BlenderDNA.h index f566554b8..871ee71a1 100644 --- a/code/AssetLib/Blender/BlenderDNA.h +++ b/code/AssetLib/Blender/BlenderDNA.h @@ -476,7 +476,7 @@ public: * in BlenderScene.cpp and is machine-generated. * Converters are used to quickly handle objects whose * exact data type is a runtime-property and not yet - * known at compile time (consier Object::data).*/ + * known at compile time (consider Object::data).*/ void RegisterConverters(); // -------------------------------------------------------- diff --git a/code/AssetLib/Blender/BlenderLoader.cpp b/code/AssetLib/Blender/BlenderLoader.cpp index 7cf4e070e..4b094936c 100644 --- a/code/AssetLib/Blender/BlenderLoader.cpp +++ b/code/AssetLib/Blender/BlenderLoader.cpp @@ -113,8 +113,8 @@ BlenderImporter::~BlenderImporter() { delete modifier_cache; } -static const char *Tokens[] = { "BLENDER" }; -static const char *TokensForSearch[] = { "blender" }; +static const char * const Tokens[] = { "BLENDER" }; +static const char * const TokensForSearch[] = { "blender" }; // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. @@ -679,7 +679,7 @@ void BlenderImporter::BuildMaterials(ConversionData &conv_data) { BuildDefaultMaterial(conv_data); - for (std::shared_ptr mat : conv_data.materials_raw) { + for (const std::shared_ptr &mat : conv_data.materials_raw) { // reset per material global counters for (size_t i = 0; i < sizeof(conv_data.next_texture) / sizeof(conv_data.next_texture[0]); ++i) { diff --git a/code/AssetLib/Blender/BlenderLoader.h b/code/AssetLib/Blender/BlenderLoader.h index 42da76514..1df0fcf90 100644 --- a/code/AssetLib/Blender/BlenderLoader.h +++ b/code/AssetLib/Blender/BlenderLoader.h @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2021, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -43,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file BlenderLoader.h * @brief Declaration of the Blender 3D (*.blend) importer class. */ +#pragma once #ifndef INCLUDED_AI_BLEND_LOADER_H #define INCLUDED_AI_BLEND_LOADER_H @@ -56,149 +56,139 @@ struct aiLight; struct aiCamera; struct aiMaterial; -namespace Assimp { +namespace Assimp { - // TinyFormatter.h - namespace Formatter { - template class basic_formatter; - typedef class basic_formatter< char, std::char_traits, std::allocator > format; - } +// TinyFormatter.h +namespace Formatter { - // BlenderDNA.h - namespace Blender { - class FileDatabase; - struct ElemBase; - } +template +class basic_formatter; - // BlenderScene.h - namespace Blender { - struct Scene; - struct Object; - struct Mesh; - struct Camera; - struct Lamp; - struct MTex; - struct Image; - struct Material; - } +typedef class basic_formatter, std::allocator> format; - // BlenderIntermediate.h - namespace Blender { - struct ConversionData; - template