From 87ac6fbfd94199c049037a5d76ab117944c26b3c Mon Sep 17 00:00:00 2001 From: "Andrea Baldacci, Ph.D" Date: Tue, 31 Oct 2017 02:05:01 +0100 Subject: [PATCH 001/278] Update CMakeLists.txt --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index c30278b7f..270aad38a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -211,6 +211,11 @@ ELSEIF( CMAKE_COMPILER_IS_MINGW ) ADD_DEFINITIONS( -U__STRICT_ANSI__ ) ENDIF() +if(IOS) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -O3") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3") +endif(IOS) + if (ASSIMP_COVERALLS) MESSAGE(STATUS "Coveralls enabled") INCLUDE(Coveralls) From 978c156c2ad84d3b8afcabbc55ff966aafe3ecec Mon Sep 17 00:00:00 2001 From: Marco Di Benedetto Date: Wed, 10 Jan 2018 20:02:41 +0100 Subject: [PATCH 002/278] added import of material properties (double sided and transparency) in glTF 1.0 importer. --- code/glTFImporter.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/code/glTFImporter.cpp b/code/glTFImporter.cpp index 381e459fd..9e341c632 100644 --- a/code/glTFImporter.cpp +++ b/code/glTFImporter.cpp @@ -193,9 +193,16 @@ void glTFImporter::ImportMaterials(glTF::Asset& r) aimat->AddProperty(&str, AI_MATKEY_NAME); } - SetMaterialColorProperty(embeddedTexIdxs, r, mat.diffuse, aimat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE); + SetMaterialColorProperty(embeddedTexIdxs, r, mat.ambient, aimat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT ); + SetMaterialColorProperty(embeddedTexIdxs, r, mat.diffuse, aimat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE ); SetMaterialColorProperty(embeddedTexIdxs, r, mat.specular, aimat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR); - SetMaterialColorProperty(embeddedTexIdxs, r, mat.ambient, aimat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT); + SetMaterialColorProperty(embeddedTexIdxs, r, mat.emission, aimat, aiTextureType_EMISSIVE, AI_MATKEY_COLOR_EMISSIVE); + + aimat->AddProperty(&mat.doubleSided, 1, AI_MATKEY_TWOSIDED); + + if (mat.transparent && (mat.transparency != 1.0f)) { + aimat->AddProperty(&mat.transparency, 1, AI_MATKEY_OPACITY); + } if (mat.shininess > 0.f) { aimat->AddProperty(&mat.shininess, 1, AI_MATKEY_SHININESS); From c749594e9de7b98ae63000aef19013dcc020d441 Mon Sep 17 00:00:00 2001 From: Marco Di Benedetto Date: Thu, 18 Jan 2018 19:12:51 +0100 Subject: [PATCH 003/278] gltf instant ok on valid extension. --- code/glTF2Importer.cpp | 4 ++-- code/glTFImporter.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 92328ec2d..8136af2dc 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -103,8 +103,8 @@ bool glTF2Importer::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool { const std::string &extension = GetExtension(pFile); - if (extension != "gltf" && extension != "glb") - return false; + if (extension == "gltf" || extension == "glb") + return true; if (pIOHandler) { glTF2::Asset asset(pIOHandler); diff --git a/code/glTFImporter.cpp b/code/glTFImporter.cpp index b4d69e32f..4df9e1763 100644 --- a/code/glTFImporter.cpp +++ b/code/glTFImporter.cpp @@ -102,8 +102,8 @@ bool glTFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool { const std::string &extension = GetExtension(pFile); - if (extension != "gltf" && extension != "glb") - return false; + if (extension == "gltf" || extension == "glb") + return true; if (pIOHandler) { glTF::Asset asset(pIOHandler); From 5f38bd01ece06876250fd3bab4f72456170cf3e4 Mon Sep 17 00:00:00 2001 From: Marco Di Benedetto Date: Thu, 18 Jan 2018 22:28:44 +0100 Subject: [PATCH 004/278] restored gltf checks. --- code/glTF2Importer.cpp | 4 ++-- code/glTFImporter.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 8136af2dc..92328ec2d 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -103,8 +103,8 @@ bool glTF2Importer::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool { const std::string &extension = GetExtension(pFile); - if (extension == "gltf" || extension == "glb") - return true; + if (extension != "gltf" && extension != "glb") + return false; if (pIOHandler) { glTF2::Asset asset(pIOHandler); diff --git a/code/glTFImporter.cpp b/code/glTFImporter.cpp index 4df9e1763..b4d69e32f 100644 --- a/code/glTFImporter.cpp +++ b/code/glTFImporter.cpp @@ -102,8 +102,8 @@ bool glTFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool { const std::string &extension = GetExtension(pFile); - if (extension == "gltf" || extension == "glb") - return true; + if (extension != "gltf" && extension != "glb") + return false; if (pIOHandler) { glTF::Asset asset(pIOHandler); From b28bcc365c1ca1063c5df4f906f73dfb49603477 Mon Sep 17 00:00:00 2001 From: Rohan Singh Date: Wed, 24 Jan 2018 09:45:20 -0500 Subject: [PATCH 005/278] Interpret IndexAToDirect as Direct when the index element is missing Paint3D exports FBX like this, which is wrong, but could still support it --- code/FBXMeshGeometry.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/code/FBXMeshGeometry.cpp b/code/FBXMeshGeometry.cpp index 4868b3e72..99e1b1c5f 100644 --- a/code/FBXMeshGeometry.cpp +++ b/code/FBXMeshGeometry.cpp @@ -427,16 +427,19 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, const std::vector& mapping_offsets, const std::vector& mappings) { + bool isDirect = ReferenceInformationType == "Direct"; + bool isIndexToDirect = ReferenceInformationType == "IndexToDirect"; + // fallback to direct data if there is no index data element + if ( isIndexToDirect && !HasElement( source, indexDataElementName ) ) { + isDirect = true; + isIndexToDirect = false; + } // handle permutations of Mapping and Reference type - it would be nice to // deal with this more elegantly and with less redundancy, but right // now it seems unavoidable. - if (MappingInformationType == "ByVertice" && ReferenceInformationType == "Direct") { - if ( !HasElement( source, indexDataElementName ) ) { - return; - } - + if (MappingInformationType == "ByVertice" && isDirect) { std::vector tempData; ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); @@ -449,14 +452,11 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, } } } - else if (MappingInformationType == "ByVertice" && ReferenceInformationType == "IndexToDirect") { + else if (MappingInformationType == "ByVertice" && isIndexToDirect) { std::vector tempData; ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); data_out.resize(vertex_count); - if ( !HasElement( source, indexDataElementName ) ) { - return; - } std::vector uvIndices; ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); @@ -471,7 +471,7 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, } } } - else if (MappingInformationType == "ByPolygonVertex" && ReferenceInformationType == "Direct") { + else if (MappingInformationType == "ByPolygonVertex" && isDirect) { std::vector tempData; ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); @@ -484,7 +484,7 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, data_out.swap(tempData); } - else if (MappingInformationType == "ByPolygonVertex" && ReferenceInformationType == "IndexToDirect") { + else if (MappingInformationType == "ByPolygonVertex" && isIndexToDirect) { std::vector tempData; ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); From 2a7ebc570c12d0793337e79ab55d9eb812d8cf0f Mon Sep 17 00:00:00 2001 From: Giuseppe Barbieri Date: Mon, 5 Feb 2018 17:13:53 +0100 Subject: [PATCH 006/278] Update Readme.md --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index ca6c9ba4d..a6f2e3d3d 100644 --- a/Readme.md +++ b/Readme.md @@ -120,7 +120,7 @@ Take a look into the `INSTALL` file. Our build system is CMake, if you used CMak * [Pascal](port/AssimpPascal/Readme.md) * [Javascript (Alpha)](https://github.com/makc/assimp2json) * [Unity 3d Plugin](https://www.assetstore.unity3d.com/en/#!/content/91777) -* [JVM](https://github.com/kotlin-graphics/assimp) Full jvm port (currently supported obj, ply, stl, collada, md2) +* [JVM](https://github.com/kotlin-graphics/assimp) Full jvm port (current [status](https://github.com/kotlin-graphics/assimp/wiki/Status)) ### Other tools ### [open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities. From 4736160b793ed86840cb07c156a469516c1c92b4 Mon Sep 17 00:00:00 2001 From: Giuseppe Barbieri Date: Tue, 6 Feb 2018 22:36:37 +0100 Subject: [PATCH 007/278] Update BlenderDNA.h --- code/BlenderDNA.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/BlenderDNA.h b/code/BlenderDNA.h index 932784e9f..43c9d2d82 100644 --- a/code/BlenderDNA.h +++ b/code/BlenderDNA.h @@ -204,7 +204,7 @@ enum ErrorPolicy { // ------------------------------------------------------------------------------- /** Represents a data structure in a BLEND file. A Structure defines n fields - * and their locatios and encodings the input stream. Usually, every + * and their locations and encodings the input stream. Usually, every * Structure instance pertains to one equally-named data structure in the * BlenderScene.h header. This class defines various utilities to map a * binary `blob` read from the file to such a structure instance with From c7ea536351ffe7114992a1903af0de0ead46e8b5 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 7 Feb 2018 20:21:05 +0100 Subject: [PATCH 008/278] closes https://github.com/assimp/assimp/issues/1386: fix undefined behaviour in compare function. --- code/BlenderDNA.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/code/BlenderDNA.cpp b/code/BlenderDNA.cpp index 285cb05b8..1d88f8fa6 100644 --- a/code/BlenderDNA.cpp +++ b/code/BlenderDNA.cpp @@ -58,12 +58,11 @@ using namespace Assimp::Formatter; static bool match4(StreamReaderAny& stream, const char* string) { ai_assert( nullptr != string ); - char tmp[] = { - (const char)(stream).GetI1(), - (const char)(stream).GetI1(), - (const char)(stream).GetI1(), - (const char)(stream).GetI1() - }; + char tmp[4]; + tmp[ 0 ] = ( stream ).GetI1(); + tmp[ 1 ] = ( stream ).GetI1(); + tmp[ 2 ] = ( stream ).GetI1(); + tmp[ 3 ] = ( stream ).GetI1(); return (tmp[0]==string[0] && tmp[1]==string[1] && tmp[2]==string[2] && tmp[3]==string[3]); } From 674a47dd3eaffa1a89db75d258d2a2cd190cbcec Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 8 Feb 2018 20:24:18 +0100 Subject: [PATCH 009/278] closes https://github.com/assimp/assimp/issues/567: prevend dependency cycle --- code/ASELoader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/ASELoader.cpp b/code/ASELoader.cpp index 122b226f4..32b0eae2d 100644 --- a/code/ASELoader.cpp +++ b/code/ASELoader.cpp @@ -583,7 +583,7 @@ void ASEImporter::AddNodes (const std::vector& nodes, node->mTransformation = mParentAdjust*snode->mTransform; // Add sub nodes - prevent stack overflow due to recursive parenting - if (node->mName != node->mParent->mName) { + if (node->mName != node->mParent->mName && node->mName != node->mParent->mParent->mName ) { AddNodes(nodes,node,node->mName.data,snode->mTransform); } From ebdad4f883adfc16133badf5087043894a773f1d Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Fri, 9 Feb 2018 15:40:28 +0200 Subject: [PATCH 010/278] Ogre: Avoid creating function-scoped static constants They're causing false positive race condition messages from Helgrind --- code/OgreXmlSerializer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/OgreXmlSerializer.cpp b/code/OgreXmlSerializer.cpp index c777cf363..78acaa7fd 100644 --- a/code/OgreXmlSerializer.cpp +++ b/code/OgreXmlSerializer.cpp @@ -835,7 +835,7 @@ void OgreXmlSerializer::ReadAnimationTracks(Animation *dest) void OgreXmlSerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *dest) { - static const aiVector3D zeroVec(0.f, 0.f, 0.f); + const aiVector3D zeroVec(0.f, 0.f, 0.f); NextNode(); while(m_currentNodeName == nnKeyFrame) From 59ea3b6c8577c4e46e8ca0ca68afcf9efa92cf0a Mon Sep 17 00:00:00 2001 From: Marco Di Benedetto Date: Fri, 9 Feb 2018 16:02:27 +0100 Subject: [PATCH 011/278] fixed android zlib compile error. --- CMakeLists.txt | 8 ++++---- contrib/zlib/zlib.h | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d3616ab7..15374a3fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -230,10 +230,10 @@ ELSEIF( CMAKE_COMPILER_IS_MINGW ) ADD_DEFINITIONS( -U__STRICT_ANSI__ ) ENDIF() -if(IOS) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -O3") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3") -endif(IOS) +if (IOS) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -O3") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3") +endif() if (ASSIMP_COVERALLS) MESSAGE(STATUS "Coveralls enabled") diff --git a/contrib/zlib/zlib.h b/contrib/zlib/zlib.h index 2d6bb2976..dcb7b5063 100644 --- a/contrib/zlib/zlib.h +++ b/contrib/zlib/zlib.h @@ -77,8 +77,9 @@ extern "C" { the consistency of the compressed data, so the library should never crash even in the case of corrupted input. */ -#ifdef __ANDROID__ -using zcrc_t = unsigned_long; + +#ifdef __ANDROID__ +typedef unsigned long zcrc_t; #endif typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); From c874fd8ae2626334f7920715d4e6977529297dff Mon Sep 17 00:00:00 2001 From: Marco Di Benedetto Date: Fri, 9 Feb 2018 16:18:49 +0100 Subject: [PATCH 012/278] changed std::to_string to to_string. --- code/3DSLoader.cpp | 2 +- code/glTFAsset.inl | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/code/3DSLoader.cpp b/code/3DSLoader.cpp index 9d61e125c..92a64e3d8 100644 --- a/code/3DSLoader.cpp +++ b/code/3DSLoader.cpp @@ -349,7 +349,7 @@ void Discreet3DSImporter::ParseObjectChunk() case Discreet3DS::CHUNK_MAT_MATERIAL: // Add a new material to the list - mScene->mMaterials.push_back(D3DS::Material(std::string("UNNAMED_" + std::to_string(mScene->mMaterials.size())))); + mScene->mMaterials.push_back(D3DS::Material(std::string("UNNAMED_" + to_string(mScene->mMaterials.size())))); ParseMaterialChunk(); break; diff --git a/code/glTFAsset.inl b/code/glTFAsset.inl index b31846abd..bd43b19f2 100644 --- a/code/glTFAsset.inl +++ b/code/glTFAsset.inl @@ -948,24 +948,24 @@ Ref buf = pAsset_Root.buffers.Get(pCompression_Open3DGC.Buffer); size_t size_coordindex = ifs.GetNCoordIndex() * 3;// See float attributes note. if(primitives[0].indices->count != size_coordindex) - throw DeadlyImportError("GLTF: Open3DGC. Compressed indices count (" + std::to_string(size_coordindex) + - ") not equal to uncompressed (" + std::to_string(primitives[0].indices->count) + ")."); + throw DeadlyImportError("GLTF: Open3DGC. Compressed indices count (" + to_string(size_coordindex) + + ") not equal to uncompressed (" + to_string(primitives[0].indices->count) + ")."); size_coordindex *= sizeof(IndicesType); // Coordinates size_t size_coord = ifs.GetNCoord();// See float attributes note. if(primitives[0].attributes.position[0]->count != size_coord) - throw DeadlyImportError("GLTF: Open3DGC. Compressed positions count (" + std::to_string(size_coord) + - ") not equal to uncompressed (" + std::to_string(primitives[0].attributes.position[0]->count) + ")."); + throw DeadlyImportError("GLTF: Open3DGC. Compressed positions count (" + to_string(size_coord) + + ") not equal to uncompressed (" + to_string(primitives[0].attributes.position[0]->count) + ")."); size_coord *= 3 * sizeof(float); // Normals size_t size_normal = ifs.GetNNormal();// See float attributes note. if(primitives[0].attributes.normal[0]->count != size_normal) - throw DeadlyImportError("GLTF: Open3DGC. Compressed normals count (" + std::to_string(size_normal) + - ") not equal to uncompressed (" + std::to_string(primitives[0].attributes.normal[0]->count) + ")."); + throw DeadlyImportError("GLTF: Open3DGC. Compressed normals count (" + to_string(size_normal) + + ") not equal to uncompressed (" + to_string(primitives[0].attributes.normal[0]->count) + ")."); size_normal *= 3 * sizeof(float); // Additional attributes. @@ -989,8 +989,8 @@ Ref buf = pAsset_Root.buffers.Get(pCompression_Open3DGC.Buffer); if(idx_texcoord < primitives[0].attributes.texcoord.size()) { if(primitives[0].attributes.texcoord[idx]->count != tval) - throw DeadlyImportError("GLTF: Open3DGC. Compressed texture coordinates count (" + std::to_string(tval) + - ") not equal to uncompressed (" + std::to_string(primitives[0].attributes.texcoord[idx]->count) + ")."); + throw DeadlyImportError("GLTF: Open3DGC. Compressed texture coordinates count (" + to_string(tval) + + ") not equal to uncompressed (" + to_string(primitives[0].attributes.texcoord[idx]->count) + ")."); idx_texcoord++; } From f00d450d254d5ba56fdad4bf004127847ee6b551 Mon Sep 17 00:00:00 2001 From: Giuseppe Barbieri Date: Sun, 11 Feb 2018 17:43:49 +0100 Subject: [PATCH 013/278] Update BlenderDNA.inl --- code/BlenderDNA.inl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/BlenderDNA.inl b/code/BlenderDNA.inl index de85815cc..c6a3779b1 100644 --- a/code/BlenderDNA.inl +++ b/code/BlenderDNA.inl @@ -501,7 +501,7 @@ const FileBlockHead* Structure :: LocateFileBlockForAddress(const Pointer & ptrv { // the file blocks appear in list sorted by // with ascending base addresses so we can run a - // binary search to locate the pointee quickly. + // binary search to locate the pointer quickly. // NOTE: Blender seems to distinguish between side-by-side // data (stored in the same data block) and far pointers, From 76b981aa2a7542e71220f737f2a8c8a22ab0d740 Mon Sep 17 00:00:00 2001 From: mbuchner Date: Mon, 12 Feb 2018 10:52:49 +0100 Subject: [PATCH 014/278] Make MemoryIOStream::Seek accept pos=length as valid Fixes assimp/assimp#1781. --- include/assimp/MemoryIOWrapper.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/assimp/MemoryIOWrapper.h b/include/assimp/MemoryIOWrapper.h index 0e9b23447..bfcfff9c2 100644 --- a/include/assimp/MemoryIOWrapper.h +++ b/include/assimp/MemoryIOWrapper.h @@ -99,19 +99,19 @@ public: // Seek specific position aiReturn Seek(size_t pOffset, aiOrigin pOrigin) { if (aiOrigin_SET == pOrigin) { - if (pOffset >= length) { + if (pOffset > length) { return AI_FAILURE; } pos = pOffset; } else if (aiOrigin_END == pOrigin) { - if (pOffset >= length) { + if (pOffset > length) { return AI_FAILURE; } pos = length-pOffset; } else { - if (pOffset+pos >= length) { + if (pOffset+pos > length) { return AI_FAILURE; } pos += pOffset; From 12999050262d8a6213cf6b1f136a11fa80f57066 Mon Sep 17 00:00:00 2001 From: mbuchner Date: Mon, 12 Feb 2018 11:20:03 +0100 Subject: [PATCH 015/278] Make FileSystemFilter forward all virtual functions to wrapped IOSystem instance This makes it possible to override those functions. Previously the default implementation was always used. Fixes #1773 --- code/FileSystemFilter.h | 49 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/code/FileSystemFilter.h b/code/FileSystemFilter.h index 0fabb41dd..10b18bd78 100644 --- a/code/FileSystemFilter.h +++ b/code/FileSystemFilter.h @@ -168,6 +168,55 @@ public: return wrapped->ComparePaths (one,second); } + // ------------------------------------------------------------------- + /** Pushes a new directory onto the directory stack. */ + bool PushDirectory(const std::string &path) + { + return wrapped->PushDirectory(path); + } + + // ------------------------------------------------------------------- + /** Returns the top directory from the stack. */ + const std::string &CurrentDirectory() const + { + return wrapped->CurrentDirectory(); + } + + // ------------------------------------------------------------------- + /** Returns the number of directories stored on the stack. */ + size_t StackSize() const + { + return wrapped->StackSize(); + } + + // ------------------------------------------------------------------- + /** Pops the top directory from the stack. */ + bool PopDirectory() + { + return wrapped->PopDirectory(); + } + + // ------------------------------------------------------------------- + /** Creates an new directory at the given path. */ + bool CreateDirectory(const std::string &path) + { + return wrapped->CreateDirectory(path); + } + + // ------------------------------------------------------------------- + /** Will change the current directory to the given path. */ + bool ChangeDirectory(const std::string &path) + { + return wrapped->ChangeDirectory(path); + } + + // ------------------------------------------------------------------- + /** Delete file. */ + bool DeleteFile(const std::string &file) + { + return wrapped->DeleteFile(file); + } + private: // ------------------------------------------------------------------- From 78173177e895e08548c1f3ecc68352d048355634 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 12 Feb 2018 21:45:47 +0100 Subject: [PATCH 016/278] closes https://github.com/assimp/assimp/issues/1564: remove copy constructor. --- code/Importer.cpp | 14 +--- include/assimp/Importer.hpp | 2 +- include/assimp/SpatialSort.h | 18 +++-- include/assimp/fast_atof.h | 147 ++++++++++++++++------------------- include/assimp/mesh.h | 47 +++++++---- 5 files changed, 115 insertions(+), 113 deletions(-) diff --git a/code/Importer.cpp b/code/Importer.cpp index 4ebc72420..feddadf58 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -190,7 +190,7 @@ Importer::~Importer() delete pimpl->mIOHandler; delete pimpl->mProgressHandler; - // Kill imported scene. Destructors should do that recursivly + // Kill imported scene. Destructor's should do that recursively delete pimpl->mScene; // Delete shared post-processing data @@ -200,18 +200,6 @@ Importer::~Importer() delete pimpl; } -// ------------------------------------------------------------------------------------------------ -// Copy constructor - copies the config of another Importer, not the scene -Importer::Importer(const Importer &other) - : pimpl(NULL) { - new(this) Importer(); - - pimpl->mIntProperties = other.pimpl->mIntProperties; - pimpl->mFloatProperties = other.pimpl->mFloatProperties; - pimpl->mStringProperties = other.pimpl->mStringProperties; - pimpl->mMatrixProperties = other.pimpl->mMatrixProperties; -} - // ------------------------------------------------------------------------------------------------ // Register a custom post-processing step aiReturn Importer::RegisterPPStep(BaseProcess* pImp) diff --git a/include/assimp/Importer.hpp b/include/assimp/Importer.hpp index 9ae8fccc6..7445c9797 100644 --- a/include/assimp/Importer.hpp +++ b/include/assimp/Importer.hpp @@ -137,7 +137,7 @@ public: * If this Importer owns a scene it won't be copied. * Call ReadFile() to start the import process. */ - Importer(const Importer& other); + Importer(const Importer& other)=delete; // ------------------------------------------------------------------- /** Assignment operator has been deleted diff --git a/include/assimp/SpatialSort.h b/include/assimp/SpatialSort.h index 323c2970f..4c45e95ad 100644 --- a/include/assimp/SpatialSort.h +++ b/include/assimp/SpatialSort.h @@ -47,8 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -namespace Assimp -{ +namespace Assimp { // ------------------------------------------------------------------------------------------------ /** A little helper class to quickly find all vertices in the epsilon environment of a given @@ -148,17 +147,20 @@ protected: aiVector3D mPlaneNormal; /** An entry in a spatially sorted position array. Consists of a vertex index, - * its position and its precalculated distance from the reference plane */ - struct Entry - { + * its position and its pre-calculated distance from the reference plane */ + struct Entry { unsigned int mIndex; ///< The vertex referred by this entry aiVector3D mPosition; ///< Position ai_real mDistance; ///< Distance of this vertex to the sorting plane - Entry() { /** intentionally not initialized.*/ } + Entry() + : mIndex( 999999999 ), mPosition(), mDistance( 99999. ) { + // empty + } Entry( unsigned int pIndex, const aiVector3D& pPosition, ai_real pDistance) - : mIndex( pIndex), mPosition( pPosition), mDistance( pDistance) - { } + : mIndex( pIndex), mPosition( pPosition), mDistance( pDistance) { + // empty + } bool operator < (const Entry& e) const { return mDistance < e.mDistance; } }; diff --git a/include/assimp/fast_atof.h b/include/assimp/fast_atof.h index 058a7ff87..06fd938c0 100644 --- a/include/assimp/fast_atof.h +++ b/include/assimp/fast_atof.h @@ -59,69 +59,65 @@ const double fast_atof_table[16] = { // we write [16] here instead of [] to wo // ------------------------------------------------------------------------------------ // Convert a string in decimal format to a number // ------------------------------------------------------------------------------------ -inline unsigned int strtoul10( const char* in, const char** out=0) -{ +inline +unsigned int strtoul10( const char* in, const char** out=0) { unsigned int value = 0; - bool running = true; - while ( running ) - { + for ( ;; ) { if ( *in < '0' || *in > '9' ) break; value = ( value * 10 ) + ( *in - '0' ); ++in; } - if (out)*out = in; + if ( out ) { + *out = in; + } return value; } // ------------------------------------------------------------------------------------ // Convert a string in octal format to a number // ------------------------------------------------------------------------------------ -inline unsigned int strtoul8( const char* in, const char** out=0) -{ - unsigned int value = 0; - - bool running = true; - while ( running ) - { - if ( *in < '0' || *in > '7' ) +inline +unsigned int strtoul8( const char* in, const char** out=0) { + unsigned int value( 0 ); + for ( ;; ) { + if ( *in < '0' || *in > '7' ) { break; + } value = ( value << 3 ) + ( *in - '0' ); ++in; } - if (out)*out = in; + if ( out ) { + *out = in; + } return value; } // ------------------------------------------------------------------------------------ // Convert a string in hex format to a number // ------------------------------------------------------------------------------------ -inline unsigned int strtoul16( const char* in, const char** out=0) -{ - unsigned int value = 0; - - bool running = true; - while ( running ) - { - if ( *in >= '0' && *in <= '9' ) - { +inline +unsigned int strtoul16( const char* in, const char** out=0) { + unsigned int value( 0 ); + for ( ;; ) { + if ( *in >= '0' && *in <= '9' ) { value = ( value << 4u ) + ( *in - '0' ); - } - else if (*in >= 'A' && *in <= 'F') - { + } else if (*in >= 'A' && *in <= 'F') { value = ( value << 4u ) + ( *in - 'A' ) + 10; - } - else if (*in >= 'a' && *in <= 'f') - { + } else if (*in >= 'a' && *in <= 'f') { value = ( value << 4u ) + ( *in - 'a' ) + 10; } - else break; + else { + break; + } ++in; } - if (out)*out = in; + if ( out ) { + *out = in; + } return value; } @@ -129,17 +125,16 @@ inline unsigned int strtoul16( const char* in, const char** out=0) // Convert just one hex digit // Return value is UINT_MAX if the input character is not a hex digit. // ------------------------------------------------------------------------------------ -inline unsigned int HexDigitToDecimal(char in) -{ - unsigned int out = UINT_MAX; - if (in >= '0' && in <= '9') +inline +unsigned int HexDigitToDecimal(char in) { + unsigned int out( UINT_MAX ); + if ( in >= '0' && in <= '9' ) { out = in - '0'; - - else if (in >= 'a' && in <= 'f') + } else if ( in >= 'a' && in <= 'f' ) { out = 10u + in - 'a'; - - else if (in >= 'A' && in <= 'F') + } else if ( in >= 'A' && in <= 'F' ) { out = 10u + in - 'A'; + } // return value is UINT_MAX if the input is not a hex digit return out; @@ -148,8 +143,8 @@ inline unsigned int HexDigitToDecimal(char in) // ------------------------------------------------------------------------------------ // Convert a hex-encoded octet (2 characters, i.e. df or 1a). // ------------------------------------------------------------------------------------ -inline uint8_t HexOctetToDecimal(const char* in) -{ +inline +uint8_t HexOctetToDecimal(const char* in) { return ((uint8_t)HexDigitToDecimal(in[0])<<4)+(uint8_t)HexDigitToDecimal(in[1]); } @@ -157,11 +152,12 @@ inline uint8_t HexOctetToDecimal(const char* in) // ------------------------------------------------------------------------------------ // signed variant of strtoul10 // ------------------------------------------------------------------------------------ -inline int strtol10( const char* in, const char** out=0) -{ +inline +int strtol10( const char* in, const char** out=0) { bool inv = (*in=='-'); - if (inv || *in=='+') + if ( inv || *in == '+' ) { ++in; + } int value = strtoul10(in,out); if (inv) { @@ -176,10 +172,9 @@ inline int strtol10( const char* in, const char** out=0) // 0NNN - oct // NNN - dec // ------------------------------------------------------------------------------------ -inline unsigned int strtoul_cppstyle( const char* in, const char** out=0) -{ - if ('0' == in[0]) - { +inline +unsigned int strtoul_cppstyle( const char* in, const char** out=0) { + if ('0' == in[0]) { return 'x' == in[1] ? strtoul16(in+2,out) : strtoul8(in+1,out); } return strtoul10(in, out); @@ -189,19 +184,20 @@ inline unsigned int strtoul_cppstyle( const char* in, const char** out=0) // Special version of the function, providing higher accuracy and safety // It is mainly used by fast_atof to prevent ugly and unwanted integer overflows. // ------------------------------------------------------------------------------------ -inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_inout=0) -{ +inline +uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_inout=0) { unsigned int cur = 0; uint64_t value = 0; - if ( *in < '0' || *in > '9' ) - throw std::invalid_argument(std::string("The string \"") + in + "\" cannot be converted into a value."); + if ( *in < '0' || *in > '9' ) { + throw std::invalid_argument( std::string( "The string \"" ) + in + "\" cannot be converted into a value." ); + } bool running = true; - while ( running ) - { - if ( *in < '0' || *in > '9' ) + for ( ;; ) { + if ( *in < '0' || *in > '9' ) { break; + } const uint64_t new_value = ( value * 10 ) + ( *in - '0' ); @@ -240,8 +236,8 @@ inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* // ------------------------------------------------------------------------------------ // signed variant of strtoul10_64 // ------------------------------------------------------------------------------------ -inline int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* max_inout = 0) -{ +inline +int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* max_inout = 0) { bool inv = (*in == '-'); if (inv || *in == '+') ++in; @@ -263,8 +259,8 @@ inline int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* m // If you find any bugs, please send them to me, niko (at) irrlicht3d.org. // ------------------------------------------------------------------------------------ template -inline const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true) -{ +inline +const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true) { Real f = 0; bool inv = (*c == '-'); @@ -272,37 +268,32 @@ inline const char* fast_atoreal_move(const char* c, Real& out, bool check_comma ++c; } - if ((c[0] == 'N' || c[0] == 'n') && ASSIMP_strincmp(c, "nan", 3) == 0) - { + if ((c[0] == 'N' || c[0] == 'n') && ASSIMP_strincmp(c, "nan", 3) == 0) { out = std::numeric_limits::quiet_NaN(); c += 3; return c; } - if ((c[0] == 'I' || c[0] == 'i') && ASSIMP_strincmp(c, "inf", 3) == 0) - { + if ((c[0] == 'I' || c[0] == 'i') && ASSIMP_strincmp(c, "inf", 3) == 0) { out = std::numeric_limits::infinity(); if (inv) { out = -out; } c += 3; - if ((c[0] == 'I' || c[0] == 'i') && ASSIMP_strincmp(c, "inity", 5) == 0) - { + if ((c[0] == 'I' || c[0] == 'i') && ASSIMP_strincmp(c, "inity", 5) == 0) { c += 5; } return c; } if (!(c[0] >= '0' && c[0] <= '9') && - !((c[0] == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9')) - { + !((c[0] == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9')) { throw std::invalid_argument("Cannot parse string " "as real number: does not start with digit " "or decimal point followed by digit."); } - if (*c != '.' && (! check_comma || c[0] != ',')) - { + if (*c != '.' && (! check_comma || c[0] != ',')) { f = static_cast( strtoul10_64 ( c, &c) ); } @@ -358,30 +349,30 @@ inline const char* fast_atoreal_move(const char* c, Real& out, bool check_comma // ------------------------------------------------------------------------------------ // The same but more human. -inline ai_real fast_atof(const char* c) -{ +inline +ai_real fast_atof(const char* c) { ai_real ret(0.0); fast_atoreal_move(c, ret); return ret; } -inline ai_real fast_atof( const char* c, const char** cout) -{ +inline +ai_real fast_atof( const char* c, const char** cout) { ai_real ret(0.0); *cout = fast_atoreal_move(c, ret); return ret; } -inline ai_real fast_atof( const char** inout) -{ +inline +ai_real fast_atof( const char** inout) { ai_real ret(0.0); *inout = fast_atoreal_move(*inout, ret); return ret; } -} // end of namespace Assimp +} //! namespace Assimp -#endif +#endif // __FAST_A_TO_F_H_INCLUDED__ diff --git a/include/assimp/mesh.h b/include/assimp/mesh.h index 5896284f6..b2f64195f 100644 --- a/include/assimp/mesh.h +++ b/include/assimp/mesh.h @@ -200,8 +200,7 @@ struct aiFace // --------------------------------------------------------------------------- /** @brief A single influence of a bone on a vertex. */ -struct aiVertexWeight -{ +struct aiVertexWeight { //! Index of the vertex which is influenced by the bone. unsigned int mVertexId; @@ -214,15 +213,26 @@ struct aiVertexWeight //! Default constructor aiVertexWeight() : mVertexId(0) - , mWeight(0.0f) - { } + , mWeight(0.0f) { + // empty + } //! Initialisation from a given index and vertex weight factor //! \param pID ID //! \param pWeight Vertex weight factor - aiVertexWeight( unsigned int pID, float pWeight) - : mVertexId( pID), mWeight( pWeight) - { /* nothing to do here */ } + aiVertexWeight( unsigned int pID, float pWeight ) + : mVertexId( pID ) + , mWeight( pWeight ) { + // empty + } + + bool operator == ( const aiVertexWeight &rhs ) const { + return ( mVertexId == rhs.mVertexId && mWeight == rhs.mWeight ); + } + + bool operator != ( const aiVertexWeight &rhs ) const { + return ( *this == rhs ); + } #endif // __cplusplus }; @@ -235,8 +245,7 @@ struct aiVertexWeight * which it can be addressed by animations. In addition it has a number of * influences on vertices. */ -struct aiBone -{ +struct aiBone { //! The name of the bone. C_STRUCT aiString mName; @@ -254,10 +263,10 @@ struct aiBone //! Default constructor aiBone() - : mName() - , mNumWeights( 0 ) - , mWeights( NULL ) - { + : mName() + , mNumWeights( 0 ) + , mWeights( nullptr ) { + // empty } //! Copy constructor @@ -298,7 +307,19 @@ struct aiBone return *this; } + bool operator == ( const aiBone &rhs ) const { + if ( mName != rhs.mName || mNumWeights != rhs.mNumWeights ) { + return false; + } + for ( size_t i = 0; i < mNumWeights; ++i ) { + if ( mWeights[ i ] != rhs.mWeights[ i ] ) { + return false; + } + } + + return true; + } //! Destructor - deletes the array of vertex weights ~aiBone() { From 8a4fd2f9477b6d624f9f94f2f1367c84e81e5a5d Mon Sep 17 00:00:00 2001 From: Sergio Acereda Date: Mon, 12 Feb 2018 21:51:40 +0100 Subject: [PATCH 017/278] globalScale process not registered --- code/PostStepRegistry.cpp | 9 +++++++-- code/ScaleProcess.cpp | 4 ++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/code/PostStepRegistry.cpp b/code/PostStepRegistry.cpp index 49f5d7375..2a5e211c1 100644 --- a/code/PostStepRegistry.cpp +++ b/code/PostStepRegistry.cpp @@ -125,6 +125,9 @@ corresponding preprocessor flag to selectively disable steps. #ifndef ASSIMP_BUILD_NO_DEBONE_PROCESS # include "DeboneProcess.h" #endif +#if (!defined ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS) +# include "ScaleProcess.h" +#endif namespace Assimp { @@ -136,7 +139,7 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out) // of sequence it is executed. Steps that are added here are not // validated - as RegisterPPStep() does - all dependencies must be given. // ---------------------------------------------------------------------------- - out.reserve(30); + out.reserve(31); #if (!defined ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS) out.push_back( new MakeLeftHandedProcess()); #endif @@ -197,7 +200,9 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out) #if (!defined ASSIMP_BUILD_NO_GENFACENORMALS_PROCESS) out.push_back( new GenFaceNormalsProcess()); #endif - +#if (!defined ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS) + out.push_back( new ScaleProcess()); +#endif // ......................................................................... // DON'T change the order of these five .. // XXX this is actually a design weakness that dates back to the time diff --git a/code/ScaleProcess.cpp b/code/ScaleProcess.cpp index ef7357b68..0f60fbdb4 100644 --- a/code/ScaleProcess.cpp +++ b/code/ScaleProcess.cpp @@ -39,6 +39,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ +#ifndef ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS + #include "ScaleProcess.h" #include @@ -104,3 +106,5 @@ void ScaleProcess::applyScaling( aiNode *currentNode ) { } } // Namespace Assimp + +#endif // !! ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS From 331e67c32d7b1e685c704d552ed08f25bb03e7ba Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 12 Feb 2018 22:07:12 +0100 Subject: [PATCH 018/278] 3mf: introduce first prototype for basematerial support. --- code/3MFXmlTags.h | 7 ++- code/D3MFImporter.cpp | 137 ++++++++++++++++++++++++++++++------------ 2 files changed, 106 insertions(+), 38 deletions(-) diff --git a/code/3MFXmlTags.h b/code/3MFXmlTags.h index 30aed0e95..20971a38f 100644 --- a/code/3MFXmlTags.h +++ b/code/3MFXmlTags.h @@ -69,6 +69,12 @@ namespace XmlTag { static const std::string objectid = "objectid"; static const std::string transform = "transform"; + // Material definitions + static const std::string basematerials = "basematerials"; + static const std::string basematerials_base = "base"; + static const std::string basematerials_name = "name"; + static const std::string basematerials_displaycolor = "displaycolor"; + static const std::string CONTENT_TYPES_ARCHIVE = "[Content_Types].xml"; static const std::string ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels"; static const std::string SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types"; @@ -83,7 +89,6 @@ namespace XmlTag { static const std::string PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture"; static const std::string PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"; static const std::string PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"; - } } // Namespace D3MF diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index 0777a55fa..823fae74c 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -68,7 +68,9 @@ namespace D3MF { class XmlSerializer { public: XmlSerializer(XmlReader* xmlReader) - : xmlReader(xmlReader) { + : xmlReader(xmlReader) + , mMeshes() + , mMaterials() { // empty } @@ -77,6 +79,10 @@ public: } void ImportXml(aiScene* scene) { + if ( nullptr != scene ) { + return; + } + scene->mRootNode = new aiNode(); std::vector children; @@ -84,7 +90,9 @@ public: if(xmlReader->getNodeName() == D3MF::XmlTag::object) { children.push_back(ReadObject(scene)); } else if(xmlReader->getNodeName() == D3MF::XmlTag::build) { - + // + } else if ( xmlReader->getNodeName() == D3MF::XmlTag::basematerials ) { + ReadBaseMaterials(); } } @@ -92,10 +100,10 @@ public: scene->mRootNode->mName.Set( "3MF" ); } - scene->mNumMeshes = static_cast(meshes.size()); + scene->mNumMeshes = static_cast( mMeshes.size()); scene->mMeshes = new aiMesh*[scene->mNumMeshes](); - std::copy(meshes.begin(), meshes.end(), scene->mMeshes); + std::copy( mMeshes.begin(), mMeshes.end(), scene->mMeshes); scene->mRootNode->mNumChildren = static_cast(children.size()); scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren](); @@ -104,8 +112,7 @@ public: } private: - aiNode* ReadObject(aiScene* scene) - { + aiNode* ReadObject(aiScene* scene) { std::unique_ptr node(new aiNode()); std::vector meshIds; @@ -124,19 +131,16 @@ private: node->mParent = scene->mRootNode; node->mName.Set(name); - size_t meshIdx = meshes.size(); + size_t meshIdx = mMeshes.size(); - while(ReadToEndElement(D3MF::XmlTag::object)) - { - if(xmlReader->getNodeName() == D3MF::XmlTag::mesh) - { + while(ReadToEndElement(D3MF::XmlTag::object)) { + if(xmlReader->getNodeName() == D3MF::XmlTag::mesh) { auto mesh = ReadMesh(); mesh->mName.Set(name); - meshes.push_back(mesh); + mMeshes.push_back(mesh); meshIds.push_back(static_cast(meshIdx)); - meshIdx++; - + ++meshIdx; } } @@ -147,19 +151,14 @@ private: std::copy(meshIds.begin(), meshIds.end(), node->mMeshes); return node.release(); - } aiMesh* ReadMesh() { aiMesh* mesh = new aiMesh(); - while(ReadToEndElement(D3MF::XmlTag::mesh)) - { - if(xmlReader->getNodeName() == D3MF::XmlTag::vertices) - { + while(ReadToEndElement(D3MF::XmlTag::mesh)) { + if(xmlReader->getNodeName() == D3MF::XmlTag::vertices) { ImportVertices(mesh); - } - else if(xmlReader->getNodeName() == D3MF::XmlTag::triangles) - { + } else if(xmlReader->getNodeName() == D3MF::XmlTag::triangles) { ImportTriangles(mesh); } } @@ -167,8 +166,7 @@ private: return mesh; } - void ImportVertices(aiMesh* mesh) - { + void ImportVertices(aiMesh* mesh) { std::vector vertices; while(ReadToEndElement(D3MF::XmlTag::vertices)) @@ -182,11 +180,9 @@ private: mesh->mVertices = new aiVector3D[mesh->mNumVertices]; std::copy(vertices.begin(), vertices.end(), mesh->mVertices); - } - aiVector3D ReadVertex() - { + aiVector3D ReadVertex() { aiVector3D vertex; vertex.x = ai_strtof(xmlReader->getAttributeValue(D3MF::XmlTag::x.c_str()), nullptr); @@ -196,15 +192,11 @@ private: return vertex; } - void ImportTriangles(aiMesh* mesh) - { + void ImportTriangles(aiMesh* mesh) { std::vector faces; - - while(ReadToEndElement(D3MF::XmlTag::triangles)) - { - if(xmlReader->getNodeName() == D3MF::XmlTag::triangle) - { + while(ReadToEndElement(D3MF::XmlTag::triangles)) { + if(xmlReader->getNodeName() == D3MF::XmlTag::triangle) { faces.push_back(ReadTriangle()); } } @@ -216,8 +208,7 @@ private: std::copy(faces.begin(), faces.end(), mesh->mFaces); } - aiFace ReadTriangle() - { + aiFace ReadTriangle() { aiFace face; face.mNumIndices = 3; @@ -229,6 +220,77 @@ private: return face; } + void ReadBaseMaterials() { + while ( ReadToEndElement( D3MF::XmlTag::basematerials ) ) { + mMaterials.push_back( readMaterialDef() ); + } + } + + bool parseColor( const char *color, aiColor4D &diffuse ) { + if ( nullptr == color ) { + return false; + } + + const size_t len( strlen( color ) ); + if ( 9 != len ) { + return false; + } + + const char *buf( color ); + if ( '#' != *buf ) { + return false; + } + + char comp[ 2 ] = { 0,0 }; + comp[ 0 ] = *buf; + ++buf; + comp[ 1 ] = *buf; + ++buf; + diffuse.r = static_cast( std::atoi( comp ) ); + + comp[ 0 ] = *buf; + ++buf; + comp[ 1 ] = *buf; + ++buf; + diffuse.g = static_cast( std::atoi( comp ) ); + + comp[ 0 ] = *buf; + ++buf; + comp[ 1 ] = *buf; + ++buf; + diffuse.b = static_cast( std::atoi( comp ) ); + + comp[ 0 ] = *buf; + ++buf; + comp[ 1 ] = *buf; + ++buf; + diffuse.a = static_cast( std::atoi( comp ) ); + + return true; + } + + aiMaterial *readMaterialDef() { + while ( ReadToEndElement( D3MF::XmlTag::basematerials_base ) ) { + const char *name( nullptr ); + const char *color( nullptr ); + if ( xmlReader->getNodeName() == D3MF::XmlTag::basematerials_name ) { + name = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_name.c_str() ); + + aiString matName; + matName.Set( name ); + aiMaterial *mat = new aiMaterial; + mat->AddProperty( &matName, AI_MATKEY_NAME ); + + color = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_displaycolor.c_str() ); + aiColor4D diffuse; + if ( parseColor( color, diffuse ) ) { + mat->AddProperty( &diffuse, 1, AI_MATKEY_COLOR_DIFFUSE ); + } + } + } + + } + private: bool ReadToStartElement(const std::string& startTag) { @@ -267,7 +329,8 @@ private: private: - std::vector meshes; + std::vector mMeshes; + std::vector mMaterials; XmlReader* xmlReader; }; From 9a7611a93ea9708bd840cf6febfb11fba3d12158 Mon Sep 17 00:00:00 2001 From: Sergio Acereda Date: Mon, 12 Feb 2018 22:33:51 +0100 Subject: [PATCH 019/278] AI_MATKEY_GLTF_... -> assimp/pbrmaterial.h --- code/glTF2Asset.h | 29 +------------- include/assimp/pbrmaterial.h | 76 ++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 27 deletions(-) create mode 100644 include/assimp/pbrmaterial.h diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 1ac1d538b..de3ae5cf8 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -137,7 +137,7 @@ namespace glTF2 // Vec/matrix types, as raw float arrays typedef float (vec3)[3]; typedef float (vec4)[4]; - typedef float (mat4)[16]; + typedef float (mat4)[16]; namespace Util { @@ -166,33 +166,8 @@ namespace glTF2 //! Magic number for GLB files #define AI_GLB_MAGIC_NUMBER "glTF" + #include - #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR "$mat.gltf.pbrMetallicRoughness.baseColorFactor", 0, 0 - #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR "$mat.gltf.pbrMetallicRoughness.metallicFactor", 0, 0 - #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR "$mat.gltf.pbrMetallicRoughness.roughnessFactor", 0, 0 - #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE aiTextureType_DIFFUSE, 1 - #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 0 - #define AI_MATKEY_GLTF_ALPHAMODE "$mat.gltf.alphaMode", 0, 0 - #define AI_MATKEY_GLTF_ALPHACUTOFF "$mat.gltf.alphaCutoff", 0, 0 - #define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS "$mat.gltf.pbrSpecularGlossiness", 0, 0 - #define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR "$mat.gltf.pbrMetallicRoughness.glossinessFactor", 0, 0 - - #define _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE "$tex.file.texCoord" - #define _AI_MATKEY_GLTF_MAPPINGNAME_BASE "$tex.mappingname" - #define _AI_MATKEY_GLTF_MAPPINGID_BASE "$tex.mappingid" - #define _AI_MATKEY_GLTF_MAPPINGFILTER_MAG_BASE "$tex.mappingfiltermag" - #define _AI_MATKEY_GLTF_MAPPINGFILTER_MIN_BASE "$tex.mappingfiltermin" - #define _AI_MATKEY_GLTF_SCALE_BASE "$tex.scale" - #define _AI_MATKEY_GLTF_STRENGTH_BASE "$tex.strength" - - #define AI_MATKEY_GLTF_TEXTURE_TEXCOORD _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, type, N - #define AI_MATKEY_GLTF_MAPPINGNAME(type, N) _AI_MATKEY_GLTF_MAPPINGNAME_BASE, type, N - #define AI_MATKEY_GLTF_MAPPINGID(type, N) _AI_MATKEY_GLTF_MAPPINGID_BASE, type, N - #define AI_MATKEY_GLTF_MAPPINGFILTER_MAG(type, N) _AI_MATKEY_GLTF_MAPPINGFILTER_MAG_BASE, type, N - #define AI_MATKEY_GLTF_MAPPINGFILTER_MIN(type, N) _AI_MATKEY_GLTF_MAPPINGFILTER_MIN_BASE, type, N - #define AI_MATKEY_GLTF_TEXTURE_SCALE(type, N) _AI_MATKEY_GLTF_SCALE_BASE, type, N - #define AI_MATKEY_GLTF_TEXTURE_STRENGTH(type, N) _AI_MATKEY_GLTF_STRENGTH_BASE, type, N - #ifdef ASSIMP_API #include "./../include/assimp/Compiler/pushpack1.h" #endif diff --git a/include/assimp/pbrmaterial.h b/include/assimp/pbrmaterial.h new file mode 100644 index 000000000..3d8f48ca1 --- /dev/null +++ b/include/assimp/pbrmaterial.h @@ -0,0 +1,76 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2018, assimp team + + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file pbrmaterial.h + * @brief Defines the material system of the library + */ +#ifndef AI_PBRMATERIAL_H_INC +#define AI_PBRMATERIAL_H_INC + +#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR "$mat.gltf.pbrMetallicRoughness.baseColorFactor", 0, 0 +#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR "$mat.gltf.pbrMetallicRoughness.metallicFactor", 0, 0 +#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR "$mat.gltf.pbrMetallicRoughness.roughnessFactor", 0, 0 +#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE aiTextureType_DIFFUSE, 1 +#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 0 +#define AI_MATKEY_GLTF_ALPHAMODE "$mat.gltf.alphaMode", 0, 0 +#define AI_MATKEY_GLTF_ALPHACUTOFF "$mat.gltf.alphaCutoff", 0, 0 +#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS "$mat.gltf.pbrSpecularGlossiness", 0, 0 +#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR "$mat.gltf.pbrMetallicRoughness.glossinessFactor", 0, 0 + +#define _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE "$tex.file.texCoord" +#define _AI_MATKEY_GLTF_MAPPINGNAME_BASE "$tex.mappingname" +#define _AI_MATKEY_GLTF_MAPPINGID_BASE "$tex.mappingid" +#define _AI_MATKEY_GLTF_MAPPINGFILTER_MAG_BASE "$tex.mappingfiltermag" +#define _AI_MATKEY_GLTF_MAPPINGFILTER_MIN_BASE "$tex.mappingfiltermin" +#define _AI_MATKEY_GLTF_SCALE_BASE "$tex.scale" +#define _AI_MATKEY_GLTF_STRENGTH_BASE "$tex.strength" + +#define AI_MATKEY_GLTF_TEXTURE_TEXCOORD _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, type, N +#define AI_MATKEY_GLTF_MAPPINGNAME(type, N) _AI_MATKEY_GLTF_MAPPINGNAME_BASE, type, N +#define AI_MATKEY_GLTF_MAPPINGID(type, N) _AI_MATKEY_GLTF_MAPPINGID_BASE, type, N +#define AI_MATKEY_GLTF_MAPPINGFILTER_MAG(type, N) _AI_MATKEY_GLTF_MAPPINGFILTER_MAG_BASE, type, N +#define AI_MATKEY_GLTF_MAPPINGFILTER_MIN(type, N) _AI_MATKEY_GLTF_MAPPINGFILTER_MIN_BASE, type, N +#define AI_MATKEY_GLTF_TEXTURE_SCALE(type, N) _AI_MATKEY_GLTF_SCALE_BASE, type, N +#define AI_MATKEY_GLTF_TEXTURE_STRENGTH(type, N) _AI_MATKEY_GLTF_STRENGTH_BASE, type, N + +#endif //!!AI_PBRMATERIAL_H_INC From 11a3ee109e0e1ad6b42918ba5ecbe83040ddb6a9 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 13 Feb 2018 11:36:05 +0100 Subject: [PATCH 020/278] Update fast_atof.h Remove unused variable. --- include/assimp/fast_atof.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/include/assimp/fast_atof.h b/include/assimp/fast_atof.h index 06fd938c0..d577b417f 100644 --- a/include/assimp/fast_atof.h +++ b/include/assimp/fast_atof.h @@ -193,7 +193,6 @@ uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_ino throw std::invalid_argument( std::string( "The string \"" ) + in + "\" cannot be converted into a value." ); } - bool running = true; for ( ;; ) { if ( *in < '0' || *in > '9' ) { break; @@ -239,8 +238,9 @@ uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_ino inline int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* max_inout = 0) { bool inv = (*in == '-'); - if (inv || *in == '+') + if (inv || *in == '+') { ++in; + } int64_t value = strtoul10_64(in, out, max_inout); if (inv) { @@ -297,8 +297,7 @@ const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true) f = static_cast( strtoul10_64 ( c, &c) ); } - if ((*c == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9') - { + if ((*c == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9') { ++c; // NOTE: The original implementation is highly inaccurate here. The precision of a single From ccbcaa2ee8482c196e6d7cb1a86b6f75d34c8ea0 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 13 Feb 2018 20:36:22 +0100 Subject: [PATCH 021/278] fix some static-analysis findings. --- code/FindInstancesProcess.h | 14 +++++----- code/OpenGEXImporter.cpp | 27 ++++++++++-------- code/SceneCombiner.cpp | 47 ++++++++++++++++---------------- code/SpatialSort.cpp | 2 +- code/VertexTriangleAdjacency.cpp | 15 ++++------ code/VertexTriangleAdjacency.h | 29 ++++++-------------- include/assimp/IOStreamBuffer.h | 4 +-- include/assimp/SGSpatialSort.h | 2 +- 8 files changed, 65 insertions(+), 75 deletions(-) diff --git a/code/FindInstancesProcess.h b/code/FindInstancesProcess.h index 2ef6c1ca7..fb2ac6eb6 100644 --- a/code/FindInstancesProcess.h +++ b/code/FindInstancesProcess.h @@ -60,9 +60,9 @@ namespace Assimp { * @param in Input mesh * @return Hash. */ -inline uint64_t GetMeshHash(aiMesh* in) -{ - ai_assert(NULL != in); +inline +uint64_t GetMeshHash(aiMesh* in) { + ai_assert(nullptr != in); // ... get an unique value representing the vertex format of the mesh const unsigned int fhash = GetMeshVFormatUnique(in); @@ -78,14 +78,14 @@ inline uint64_t GetMeshHash(aiMesh* in) /** @brief Perform a component-wise comparison of two arrays * * @param first First array - * @param second Second aray + * @param second Second array * @param size Size of both arrays * @param e Epsilon * @return true if the arrays are identical */ -inline bool CompareArrays(const aiVector3D* first, const aiVector3D* second, - unsigned int size, float e) -{ +inline +bool CompareArrays(const aiVector3D* first, const aiVector3D* second, + unsigned int size, float e) { for (const aiVector3D* end = first+size; first != end; ++first,++second) { if ( (*first - *second).SquareLength() >= e) return false; diff --git a/code/OpenGEXImporter.cpp b/code/OpenGEXImporter.cpp index 43c92c4f5..652ba0f98 100644 --- a/code/OpenGEXImporter.cpp +++ b/code/OpenGEXImporter.cpp @@ -731,17 +731,22 @@ enum MeshAttribute { TexCoord }; +static const std::string PosToken = "position"; +static const std::string ColToken = "color"; +static const std::string NormalToken = "normal"; +static const std::string TexCoordToken = "texcoord"; + //------------------------------------------------------------------------------------------------ static MeshAttribute getAttributeByName( const char *attribName ) { ai_assert( nullptr != attribName ); - if ( 0 == strncmp( "position", attribName, strlen( "position" ) ) ) { + if ( 0 == strncmp( PosToken.c_str(), attribName, PosToken.size() ) ) { return Position; - } else if ( 0 == strncmp( "color", attribName, strlen( "color" ) ) ) { + } else if ( 0 == strncmp( ColToken.c_str(), attribName, ColToken.size() ) ) { return Color; - } else if( 0 == strncmp( "normal", attribName, strlen( "normal" ) ) ) { + } else if( 0 == strncmp( NormalToken.c_str(), attribName, NormalToken.size() ) ) { return Normal; - } else if( 0 == strncmp( "texcoord", attribName, strlen( "texcoord" ) ) ) { + } else if( 0 == strncmp( TexCoordToken.c_str(), attribName, TexCoordToken.size() ) ) { return TexCoord; } @@ -1098,14 +1103,12 @@ void OpenGEXImporter::handleParamNode( ODDLParser::DDLNode *node, aiScene * /*pS return; } const float floatVal( val->getFloat() ); - if ( prop->m_value != nullptr ) { - if ( 0 == ASSIMP_strincmp( "fov", prop->m_value->getString(), 3 ) ) { - m_currentCamera->mHorizontalFOV = floatVal; - } else if ( 0 == ASSIMP_strincmp( "near", prop->m_value->getString(), 3 ) ) { - m_currentCamera->mClipPlaneNear = floatVal; - } else if ( 0 == ASSIMP_strincmp( "far", prop->m_value->getString(), 3 ) ) { - m_currentCamera->mClipPlaneFar = floatVal; - } + if ( 0 == ASSIMP_strincmp( "fov", prop->m_value->getString(), 3 ) ) { + m_currentCamera->mHorizontalFOV = floatVal; + } else if ( 0 == ASSIMP_strincmp( "near", prop->m_value->getString(), 4 ) ) { + m_currentCamera->mClipPlaneNear = floatVal; + } else if ( 0 == ASSIMP_strincmp( "far", prop->m_value->getString(), 3 ) ) { + m_currentCamera->mClipPlaneFar = floatVal; } } } diff --git a/code/SceneCombiner.cpp b/code/SceneCombiner.cpp index 30722618f..8647bd1ba 100644 --- a/code/SceneCombiner.cpp +++ b/code/SceneCombiner.cpp @@ -1256,29 +1256,30 @@ void SceneCombiner::Copy(aiMetadata** _dest, const aiMetadata* src) { aiMetadataEntry& out = dest->mValues[i]; out.mType = in.mType; switch (dest->mValues[i].mType) { - case AI_BOOL: - out.mData = new bool(*static_cast(in.mData)); - break; - case AI_INT32: - out.mData = new int32_t(*static_cast(in.mData)); - break; - case AI_UINT64: - out.mData = new uint64_t(*static_cast(in.mData)); - break; - case AI_FLOAT: - out.mData = new float(*static_cast(in.mData)); - break; - case AI_DOUBLE: - out.mData = new double(*static_cast(in.mData)); - break; - case AI_AISTRING: - out.mData = new aiString(*static_cast(in.mData)); - break; - case AI_AIVECTOR3D: - out.mData = new aiVector3D(*static_cast(in.mData)); - break; - default: - ai_assert(false); + case AI_BOOL: + out.mData = new bool(*static_cast(in.mData)); + break; + case AI_INT32: + out.mData = new int32_t(*static_cast(in.mData)); + break; + case AI_UINT64: + out.mData = new uint64_t(*static_cast(in.mData)); + break; + case AI_FLOAT: + out.mData = new float(*static_cast(in.mData)); + break; + case AI_DOUBLE: + out.mData = new double(*static_cast(in.mData)); + break; + case AI_AISTRING: + out.mData = new aiString(*static_cast(in.mData)); + break; + case AI_AIVECTOR3D: + out.mData = new aiVector3D(*static_cast(in.mData)); + break; + default: + ai_assert(false); + break; } } } diff --git a/code/SpatialSort.cpp b/code/SpatialSort.cpp index 010cad7c1..e6ffeb260 100644 --- a/code/SpatialSort.cpp +++ b/code/SpatialSort.cpp @@ -294,7 +294,7 @@ void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition, index++; // Now start iterating from there until the first position lays outside of the distance range. - // Add all positions inside the distance range within the tolerance to the result aray + // Add all positions inside the distance range within the tolerance to the result array std::vector::const_iterator it = mPositions.begin() + index; while( ToBinary(it->mDistance) < maxDistBinary) { diff --git a/code/VertexTriangleAdjacency.cpp b/code/VertexTriangleAdjacency.cpp index 022d5d902..5886ca372 100644 --- a/code/VertexTriangleAdjacency.cpp +++ b/code/VertexTriangleAdjacency.cpp @@ -48,7 +48,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "VertexTriangleAdjacency.h" #include - using namespace Assimp; // ------------------------------------------------------------------------------------------------ @@ -60,8 +59,8 @@ VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces, // compute the number of referenced vertices if it wasn't specified by the caller const aiFace* const pcFaceEnd = pcFaces + iNumFaces; if (!iNumVertices) { - for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) { + ai_assert( nullptr != pcFace ); ai_assert(3 == pcFace->mNumIndices); iNumVertices = std::max(iNumVertices,pcFace->mIndices[0]); iNumVertices = std::max(iNumVertices,pcFace->mIndices[1]); @@ -69,19 +68,18 @@ VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces, } } - this->iNumVertices = iNumVertices; + mNumVertices = iNumVertices; unsigned int* pi; // allocate storage if (bComputeNumTriangles) { pi = mLiveTriangles = new unsigned int[iNumVertices+1]; - memset(mLiveTriangles,0,sizeof(unsigned int)*(iNumVertices+1)); + ::memset(mLiveTriangles,0,sizeof(unsigned int)*(iNumVertices+1)); mOffsetTable = new unsigned int[iNumVertices+2]+1; - } - else { + } else { pi = mOffsetTable = new unsigned int[iNumVertices+2]+1; - memset(mOffsetTable,0,sizeof(unsigned int)*(iNumVertices+1)); + ::memset(mOffsetTable,0,sizeof(unsigned int)*(iNumVertices+1)); mLiveTriangles = NULL; // important, otherwise the d'tor would crash } @@ -90,8 +88,7 @@ VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces, *piEnd++ = 0u; // first pass: compute the number of faces referencing each vertex - for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) - { + for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) { pi[pcFace->mIndices[0]]++; pi[pcFace->mIndices[1]]++; pi[pcFace->mIndices[2]]++; diff --git a/code/VertexTriangleAdjacency.h b/code/VertexTriangleAdjacency.h index 566783835..23624a5be 100644 --- a/code/VertexTriangleAdjacency.h +++ b/code/VertexTriangleAdjacency.h @@ -60,10 +60,8 @@ namespace Assimp { * @note Although it is called #VertexTriangleAdjacency, the current version does also * support arbitrary polygons. */ // -------------------------------------------------------------------------------------------- -class ASSIMP_API VertexTriangleAdjacency -{ +class ASSIMP_API VertexTriangleAdjacency { public: - // ---------------------------------------------------------------------------- /** @brief Construction from an existing index buffer * @param pcFaces Index buffer @@ -77,39 +75,30 @@ public: unsigned int iNumVertices = 0, bool bComputeNumTriangles = true); - // ---------------------------------------------------------------------------- /** @brief Destructor */ ~VertexTriangleAdjacency(); - -public: - // ---------------------------------------------------------------------------- /** @brief Get all triangles adjacent to a vertex * @param iVertIndex Index of the vertex * @return A pointer to the adjacency list. */ - unsigned int* GetAdjacentTriangles(unsigned int iVertIndex) const - { - ai_assert(iVertIndex < iNumVertices); + unsigned int* GetAdjacentTriangles(unsigned int iVertIndex) const { + ai_assert(iVertIndex < mNumVertices); return &mAdjacencyTable[ mOffsetTable[iVertIndex]]; } - // ---------------------------------------------------------------------------- /** @brief Get the number of triangles that are referenced by * a vertex. This function returns a reference that can be modified * @param iVertIndex Index of the vertex * @return Number of referenced triangles */ - unsigned int& GetNumTrianglesPtr(unsigned int iVertIndex) - { - ai_assert(iVertIndex < iNumVertices && NULL != mLiveTriangles); + unsigned int& GetNumTrianglesPtr(unsigned int iVertIndex) { + ai_assert( iVertIndex < mNumVertices ); + ai_assert( nullptr != mLiveTriangles ); return mLiveTriangles[iVertIndex]; } - -public: - //! Offset table unsigned int* mOffsetTable; @@ -120,9 +109,9 @@ public: unsigned int* mLiveTriangles; //! Debug: Number of referenced vertices - unsigned int iNumVertices; - + unsigned int mNumVertices; }; -} + +} //! ns Assimp #endif // !! AI_VTADJACENCY_H_INC diff --git a/include/assimp/IOStreamBuffer.h b/include/assimp/IOStreamBuffer.h index a503b3874..fdc339062 100644 --- a/include/assimp/IOStreamBuffer.h +++ b/include/assimp/IOStreamBuffer.h @@ -248,9 +248,9 @@ bool IOStreamBuffer::getNextDataLine( std::vector &buffer, T continuationT } } - bool continuationFound( false ), endOfDataLine( false ); + bool continuationFound( false ); size_t i = 0; - while ( !endOfDataLine ) { + for( ;; ) { if ( continuationToken == m_cache[ m_cachePos ] ) { continuationFound = true; ++m_cachePos; diff --git a/include/assimp/SGSpatialSort.h b/include/assimp/SGSpatialSort.h index d8b4b418b..203e32512 100644 --- a/include/assimp/SGSpatialSort.h +++ b/include/assimp/SGSpatialSort.h @@ -123,7 +123,7 @@ protected: Entry() { /** intentionally not initialized.*/ } Entry( unsigned int pIndex, const aiVector3D& pPosition, float pDistance,uint32_t pSG) - : + : mIndex( pIndex), mPosition( pPosition), mSmoothGroups (pSG), From c4ff978a2f4227434f530dd83979e1f099cfe1fd Mon Sep 17 00:00:00 2001 From: Tommy Date: Fri, 16 Feb 2018 12:06:14 +0100 Subject: [PATCH 022/278] Some StreamWriter improvements / additions. Added the following functions: * Flush() to flush the internal StreamWriter buffer to the stream * Tell() gives the current stream position * Seek() seeks to a given offset in the stream * PutString(aiString&) to write an aiString * PutString(std::string&) to write a std::string --- include/assimp/StreamWriter.h | 60 ++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/include/assimp/StreamWriter.h b/include/assimp/StreamWriter.h index 7ee0944a7..e955a7255 100644 --- a/include/assimp/StreamWriter.h +++ b/include/assimp/StreamWriter.h @@ -58,7 +58,7 @@ namespace Assimp { // -------------------------------------------------------------------------------------------- /** Wrapper class around IOStream to allow for consistent writing of binary data in both * little and big endian format. Don't attempt to instance the template directly. Use - * StreamWriterLE to read from a little-endian stream and StreamWriterBE to read from a + * StreamWriterLE to write to a little-endian stream and StreamWriterBE to write to a * BE stream. Alternatively, there is StreamWriterAny if the endianness of the output * stream is to be determined at runtime. */ @@ -108,6 +108,38 @@ public: stream->Flush(); } +public: + + // --------------------------------------------------------------------- + /** Flush the contents of the internal buffer, and the output IOStream */ + void Flush() + { + stream->Write(&buffer[0], 1, buffer.size()); + stream->Flush(); + buffer.clear(); + cursor = 0; + } + + // --------------------------------------------------------------------- + /** Seek to the given offset / origin in the output IOStream. + * + * Flushes the internal buffer and the output IOStream prior to seeking. */ + aiReturn Seek(size_t pOffset, aiOrigin pOrigin=aiOrigin_SET) + { + Flush(); + return stream->Seek(pOffset, pOrigin); + } + + // --------------------------------------------------------------------- + /** Tell the current position in the output IOStream. + * + * First flushes the internal buffer and the output IOStream. */ + size_t Tell() + { + Flush(); + return stream->Tell(); + } + public: // --------------------------------------------------------------------- @@ -171,6 +203,32 @@ public: Put(n); } + // --------------------------------------------------------------------- + /** Write an aiString to the stream */ + void PutString(const aiString& s) + { + // as Put(T f) below + if (cursor + s.length >= buffer.size()) { + buffer.resize(cursor + s.length); + } + void* dest = &buffer[cursor]; + ::memcpy(dest, s.C_Str(), s.length); + cursor += s.length; + } + + // --------------------------------------------------------------------- + /** Write a std::string to the stream */ + void PutString(const std::string& s) + { + // as Put(T f) below + if (cursor + s.size() >= buffer.size()) { + buffer.resize(cursor + s.size()); + } + void* dest = &buffer[cursor]; + ::memcpy(dest, s.c_str(), s.size()); + cursor += s.size(); + } + public: // --------------------------------------------------------------------- From b9e60e674e5f2e4f746f2a91187f3544a822d0a4 Mon Sep 17 00:00:00 2001 From: Sergio Acereda Date: Fri, 16 Feb 2018 12:23:21 +0100 Subject: [PATCH 023/278] define missing type,N params --- include/assimp/pbrmaterial.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/assimp/pbrmaterial.h b/include/assimp/pbrmaterial.h index 3d8f48ca1..cd9b5e2bf 100644 --- a/include/assimp/pbrmaterial.h +++ b/include/assimp/pbrmaterial.h @@ -65,7 +65,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define _AI_MATKEY_GLTF_SCALE_BASE "$tex.scale" #define _AI_MATKEY_GLTF_STRENGTH_BASE "$tex.strength" -#define AI_MATKEY_GLTF_TEXTURE_TEXCOORD _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, type, N +#define AI_MATKEY_GLTF_TEXTURE_TEXCOORD(type, N) _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, type, N #define AI_MATKEY_GLTF_MAPPINGNAME(type, N) _AI_MATKEY_GLTF_MAPPINGNAME_BASE, type, N #define AI_MATKEY_GLTF_MAPPINGID(type, N) _AI_MATKEY_GLTF_MAPPINGID_BASE, type, N #define AI_MATKEY_GLTF_MAPPINGFILTER_MAG(type, N) _AI_MATKEY_GLTF_MAPPINGFILTER_MAG_BASE, type, N From 58436068e7e08e496a1d415461de706a33f7832f Mon Sep 17 00:00:00 2001 From: Giuseppe Barbieri Date: Fri, 16 Feb 2018 22:16:10 +0100 Subject: [PATCH 024/278] Update BlenderScene.cpp --- code/BlenderScene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/BlenderScene.cpp b/code/BlenderScene.cpp index 0e1dec7f3..e4373909e 100644 --- a/code/BlenderScene.cpp +++ b/code/BlenderScene.cpp @@ -116,7 +116,7 @@ template <> void Structure :: Convert ( ReadField(temp,"projy",db); dest.projy = static_cast(temp); ReadField(temp,"projz",db); - dest.projx = static_cast(temp); + dest.projz = static_cast(temp); ReadField(dest.mapping,"mapping",db); ReadFieldArray(dest.ofs,"ofs",db); ReadFieldArray(dest.size,"size",db); From 8950504cf079d60a18c56796218c722d52120db2 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 18 Feb 2018 21:30:23 +0100 Subject: [PATCH 025/278] Fix import of materials. --- code/3MFXmlTags.h | 1 + code/D3MFImporter.cpp | 30 ++++++++++++++++++++++-------- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/code/3MFXmlTags.h b/code/3MFXmlTags.h index 20971a38f..00938a45e 100644 --- a/code/3MFXmlTags.h +++ b/code/3MFXmlTags.h @@ -62,6 +62,7 @@ namespace XmlTag { static const std::string v2 = "v2"; static const std::string v3 = "v3"; static const std::string id = "id"; + static const std::string pid = "pid"; static const std::string name = "name"; static const std::string type = "type"; static const std::string build = "build"; diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index 823fae74c..29e27371e 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -79,7 +79,7 @@ public: } void ImportXml(aiScene* scene) { - if ( nullptr != scene ) { + if ( nullptr == scene ) { return; } @@ -87,11 +87,12 @@ public: std::vector children; while(ReadToEndElement(D3MF::XmlTag::model)) { - if(xmlReader->getNodeName() == D3MF::XmlTag::object) { + const std::string nodeName( xmlReader->getNodeName() ); + if( nodeName == D3MF::XmlTag::object) { children.push_back(ReadObject(scene)); - } else if(xmlReader->getNodeName() == D3MF::XmlTag::build) { + } else if( nodeName == D3MF::XmlTag::build) { // - } else if ( xmlReader->getNodeName() == D3MF::XmlTag::basematerials ) { + } else if ( nodeName == D3MF::XmlTag::basematerials ) { ReadBaseMaterials(); } } @@ -105,6 +106,11 @@ public: std::copy( mMeshes.begin(), mMeshes.end(), scene->mMeshes); + scene->mNumMaterials = mMaterials.size(); + if ( 0 != scene->mNumMaterials ) { + scene->mMaterials = new aiMaterial*[ scene->mNumMaterials ]; + std::copy( mMaterials.begin(), mMaterials.end(), scene->mMaterials ); + } scene->mRootNode->mNumChildren = static_cast(children.size()); scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren](); @@ -196,8 +202,13 @@ private: std::vector faces; while(ReadToEndElement(D3MF::XmlTag::triangles)) { + const std::string nodeName( xmlReader->getNodeName() ); if(xmlReader->getNodeName() == D3MF::XmlTag::triangle) { faces.push_back(ReadTriangle()); + } else if ( nodeName == D3MF::XmlTag::pid ) { + const std::string matId( xmlReader->getAttributeValue( nodeName.c_str() ) ); + int matIdx( std::atoi( matId.c_str() ) ); + mesh->mMaterialIndex = matIdx; } } @@ -270,15 +281,17 @@ private: } aiMaterial *readMaterialDef() { - while ( ReadToEndElement( D3MF::XmlTag::basematerials_base ) ) { + aiMaterial *mat( nullptr ); + //while ( ReadToEndElement( D3MF::XmlTag::basematerials_base ) ) { const char *name( nullptr ); const char *color( nullptr ); - if ( xmlReader->getNodeName() == D3MF::XmlTag::basematerials_name ) { + const std::string nodeName( xmlReader->getNodeName() ); + if ( nodeName == D3MF::XmlTag::basematerials_base ) { name = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_name.c_str() ); aiString matName; matName.Set( name ); - aiMaterial *mat = new aiMaterial; + mat = new aiMaterial; mat->AddProperty( &matName, AI_MATKEY_NAME ); color = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_displaycolor.c_str() ); @@ -287,8 +300,9 @@ private: mat->AddProperty( &diffuse, 1, AI_MATKEY_COLOR_DIFFUSE ); } } - } + //} + return mat; } private: From 24d452e27c40a1de917fb033c38688e090ebd83c Mon Sep 17 00:00:00 2001 From: Tommy Date: Mon, 19 Feb 2018 11:34:26 +0100 Subject: [PATCH 026/278] Fix aiBone->mOffsetMatrix documentation, which was incorrect. Also elaborated a bit on what mOffsetMatrix is, and what it is for. --- include/assimp/mesh.h | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/include/assimp/mesh.h b/include/assimp/mesh.h index b2f64195f..731053614 100644 --- a/include/assimp/mesh.h +++ b/include/assimp/mesh.h @@ -243,20 +243,31 @@ struct aiVertexWeight { * * A bone has a name by which it can be found in the frame hierarchy and by * which it can be addressed by animations. In addition it has a number of - * influences on vertices. + * influences on vertices, and a matrix relating the mesh position to the + * position of the bone at the time of binding. */ struct aiBone { //! The name of the bone. C_STRUCT aiString mName; - //! The number of vertices affected by this bone + //! The number of vertices affected by this bone. //! The maximum value for this member is #AI_MAX_BONE_WEIGHTS. unsigned int mNumWeights; - //! The vertices affected by this bone + //! The influence weights of this bone, by vertex index. C_STRUCT aiVertexWeight* mWeights; - //! Matrix that transforms from mesh space to bone space in bind pose + /** Matrix that transforms from bone space to mesh space in bind pose. + * + * This matrix describes the position of the mesh + * in the local space of this bone when the skeleton was bound. + * Thus it can be used directly to determine a desired vertex position, + * given the world-space transform of the bone when animated, + * and the position of the vertex in mesh space. + * + * It is sometimes called an inverse-bind matrix, + * or inverse bind pose matrix. + */ C_STRUCT aiMatrix4x4 mOffsetMatrix; #ifdef __cplusplus From 242b5d58742d963dad899af947d5e6844b753e44 Mon Sep 17 00:00:00 2001 From: Tommy Date: Mon, 19 Feb 2018 13:46:02 +0100 Subject: [PATCH 027/278] Initial FBX Export Support, sponsored by MyDidimo (mydidimo.com). Supports: * mesh data with normals and uvs * lambert and phong materials * file textures * bones / skeletons * skinning Does not yet support: * animations * cameras * lights * embedded textures --- CREDITS | 17 +- code/CMakeLists.txt | 9 +- code/Exporter.cpp | 7 + code/FBXCommon.h | 86 ++ code/FBXExportNode.cpp | 284 +++++ code/FBXExportNode.h | 197 ++++ code/FBXExportProperty.cpp | 201 ++++ code/FBXExportProperty.h | 123 +++ code/FBXExporter.cpp | 2036 ++++++++++++++++++++++++++++++++++++ code/FBXExporter.h | 146 +++ 10 files changed, 3104 insertions(+), 2 deletions(-) create mode 100644 code/FBXCommon.h create mode 100644 code/FBXExportNode.cpp create mode 100644 code/FBXExportNode.h create mode 100644 code/FBXExportProperty.cpp create mode 100644 code/FBXExportProperty.h create mode 100644 code/FBXExporter.cpp create mode 100644 code/FBXExporter.h diff --git a/CREDITS b/CREDITS index df41c482d..26e21d2f4 100644 --- a/CREDITS +++ b/CREDITS @@ -157,12 +157,27 @@ Contributed ExportProperties interface Contributed X File exporter Contributed Step (stp) exporter +- Thomas Iorns (mesilliac) +Initial FBX Export support + For a more detailed list just check: https://github.com/assimp/assimp/network/members -Patreons: + +======== +Patreons +======== + +Huge thanks to our Patreons! + - migenius - Marcus - Cort - elect - Steffen + +=================== +Commercial Sponsors +=================== + +- MyDidimo (mydidimo.com): Sponsored development of FBX Export support diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 376725e7e..6430187b0 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -522,6 +522,13 @@ ADD_ASSIMP_IMPORTER( FBX FBXDeformer.cpp FBXBinaryTokenizer.cpp FBXDocumentUtil.cpp + FBXExporter.h + FBXExporter.cpp + FBXExportNode.h + FBXExportNode.cpp + FBXExportProperty.h + FBXExportProperty.cpp + FBXCommon.h ) SET( PostProcessing_SRCS @@ -641,7 +648,7 @@ ADD_ASSIMP_IMPORTER( X XFileExporter.cpp ) -ADD_ASSIMP_IMPORTER(X3D +ADD_ASSIMP_IMPORTER( X3D X3DExporter.cpp X3DExporter.hpp X3DImporter.cpp diff --git a/code/Exporter.cpp b/code/Exporter.cpp index 51c639cfd..4951c70ef 100644 --- a/code/Exporter.cpp +++ b/code/Exporter.cpp @@ -97,6 +97,8 @@ void ExportSceneGLB2(const char*, IOSystem*, const aiScene*, const ExportPropert void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperties*); +void ExportSceneFBX(const char*, IOSystem*, const aiScene*, const ExportProperties*); +//void ExportSceneFBXA(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportScene3MF( const char*, IOSystem*, const aiScene*, const ExportProperties* ); // ------------------------------------------------------------------------------------------------ @@ -169,6 +171,11 @@ Exporter::ExportFormatEntry gExporters[] = Exporter::ExportFormatEntry( "x3d", "Extensible 3D", "x3d" , &ExportSceneX3D, 0 ), #endif +#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER + Exporter::ExportFormatEntry( "fbx", "Autodesk FBX (binary)", "fbx", &ExportSceneFBX, 0 ), + //Exporter::ExportFormatEntry( "fbxa", "Autodesk FBX (ascii)", "fbx", &ExportSceneFBXA, 0 ), +#endif + #ifndef ASSIMP_BUILD_NO_3MF_EXPORTER Exporter::ExportFormatEntry( "3mf", "The 3MF-File-Format", "3mf", &ExportScene3MF, 0 ) #endif diff --git a/code/FBXCommon.h b/code/FBXCommon.h new file mode 100644 index 000000000..60b040552 --- /dev/null +++ b/code/FBXCommon.h @@ -0,0 +1,86 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2018, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file FBXCommon.h +* Some useful constants and enums for dealing with FBX files. +*/ +#ifndef AI_FBXCOMMON_H_INC +#define AI_FBXCOMMON_H_INC + +#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER + + +namespace FBX +{ + const std::string NULL_RECORD = { // 13 null bytes + '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0' + }; // who knows why + const std::string SEPARATOR = {'\x00', '\x01'}; // for use inside strings + const std::string MAGIC_NODE_TAG = "_$AssimpFbx$"; // from import + const int64_t SECOND = 46186158000; // FBX's kTime unit + + // rotation order. We'll probably use EulerXYZ for everything + enum RotOrder { + RotOrder_EulerXYZ = 0, + RotOrder_EulerXZY, + RotOrder_EulerYZX, + RotOrder_EulerYXZ, + RotOrder_EulerZXY, + RotOrder_EulerZYX, + + RotOrder_SphericXYZ, + + RotOrder_MAX // end-of-enum sentinel + }; + + // transformation inheritance method. Most of the time RSrs + enum TransformInheritance { + TransformInheritance_RrSs = 0, + TransformInheritance_RSrs, + TransformInheritance_Rrs, + + TransformInheritance_MAX // end-of-enum sentinel + }; +} + +#endif // ASSIMP_BUILD_NO_FBX_EXPORTER + +#endif // AI_FBXCOMMON_H_INC diff --git a/code/FBXExportNode.cpp b/code/FBXExportNode.cpp new file mode 100644 index 000000000..f218f068d --- /dev/null +++ b/code/FBXExportNode.cpp @@ -0,0 +1,284 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2018, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ +#ifndef ASSIMP_BUILD_NO_EXPORT +#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER + +#include "FBXExportNode.h" +#include "FBXCommon.h" + +#include // StreamWriterLE +#include + +#include +#include // shared_ptr + +// AddP70 helpers... there's no usable pattern here, +// so all are defined as separate functions. +// Even "animatable" properties are often completely different +// from the standard (nonanimated) property definition, +// so they are specified with an 'A' suffix. + +void FBX::Node::AddP70int( + const std::string& name, int32_t value +) { + FBX::Node n("P"); + n.AddProperties(name, "int", "Integer", "", value); + AddChild(n); +} + +void FBX::Node::AddP70bool( + const std::string& name, bool value +) { + FBX::Node n("P"); + n.AddProperties(name, "bool", "", "", int32_t(value)); + AddChild(n); +} + +void FBX::Node::AddP70double( + const std::string& name, double value +) { + FBX::Node n("P"); + n.AddProperties(name, "double", "Number", "", value); + AddChild(n); +} + +void FBX::Node::AddP70numberA( + const std::string& name, double value +) { + FBX::Node n("P"); + n.AddProperties(name, "Number", "", "A", value); + AddChild(n); +} + +void FBX::Node::AddP70color( + const std::string& name, double r, double g, double b +) { + FBX::Node n("P"); + n.AddProperties(name, "ColorRGB", "Color", "", r, g, b); + AddChild(n); +} + +void FBX::Node::AddP70colorA( + const std::string& name, double r, double g, double b +) { + FBX::Node n("P"); + n.AddProperties(name, "Color", "", "A", r, g, b); + AddChild(n); +} + +void FBX::Node::AddP70vector( + const std::string& name, double x, double y, double z +) { + FBX::Node n("P"); + n.AddProperties(name, "Vector3D", "Vector", "", x, y, z); + AddChild(n); +} + +void FBX::Node::AddP70vectorA( + const std::string& name, double x, double y, double z +) { + FBX::Node n("P"); + n.AddProperties(name, "Vector", "", "A", x, y, z); + AddChild(n); +} + +void FBX::Node::AddP70string( + const std::string& name, const std::string& value +) { + FBX::Node n("P"); + n.AddProperties(name, "KString", "", "", value); + AddChild(n); +} + +void FBX::Node::AddP70enum( + const std::string& name, int32_t value +) { + FBX::Node n("P"); + n.AddProperties(name, "enum", "", "", value); + AddChild(n); +} + +void FBX::Node::AddP70time( + const std::string& name, int64_t value +) { + FBX::Node n("P"); + n.AddProperties(name, "KTime", "Time", "", value); + AddChild(n); +} + + +// public member functions for writing to binary fbx + +void FBX::Node::Dump(std::shared_ptr outfile) +{ + Assimp::StreamWriterLE outstream(outfile); + Dump(outstream); +} + +void FBX::Node::Dump(Assimp::StreamWriterLE &s) +{ + // write header section (with placeholders for some things) + Begin(s); + + // write properties + DumpProperties(s); + + // go back and fill in property related placeholders + EndProperties(s, properties.size()); + + // write children + DumpChildren(s); + + // finish, filling in end offset placeholder + End(s, !children.empty()); +} + +void FBX::Node::Begin(Assimp::StreamWriterLE &s) +{ + // remember start pos so we can come back and write the end pos + this->start_pos = s.Tell(); + + // placeholders for end pos and property section info + s.PutU4(0); // end pos + s.PutU4(0); // number of properties + s.PutU4(0); // total property section length + + // node name + s.PutU1(name.size()); // length of node name + s.PutString(name); // node name as raw bytes + + // property data comes after here + this->property_start = s.Tell(); +} + +void FBX::Node::DumpProperties(Assimp::StreamWriterLE& s) +{ + for (auto &p : properties) { + p.Dump(s); + } +} + +void FBX::Node::DumpChildren(Assimp::StreamWriterLE& s) +{ + for (FBX::Node& child : children) { + child.Dump(s); + } +} + +void FBX::Node::EndProperties(Assimp::StreamWriterLE &s) +{ + EndProperties(s, properties.size()); +} + +void FBX::Node::EndProperties( + Assimp::StreamWriterLE &s, + size_t num_properties +) { + if (num_properties == 0) { return; } + size_t pos = s.Tell(); + ai_assert(pos > property_start); + size_t property_section_size = pos - property_start; + s.Seek(start_pos + 4); + s.PutU4(num_properties); + s.PutU4(property_section_size); + s.Seek(pos); +} + +void FBX::Node::End( + Assimp::StreamWriterLE &s, + bool has_children +) { + // if there were children, add a null record + if (has_children) { s.PutString(FBX::NULL_RECORD); } + + // now go back and write initial pos + this->end_pos = s.Tell(); + s.Seek(start_pos); + s.PutU4(end_pos); + s.Seek(end_pos); +} + + +// static member functions + +// convenience function to create and write a property node, +// holding a single property which is an array of values. +// does not copy the data, so is efficient for large arrays. +// TODO: optional zip compression! +void FBX::Node::WritePropertyNode( + const std::string& name, + const std::vector& v, + Assimp::StreamWriterLE& s +){ + Node node(name); + node.Begin(s); + s.PutU1('d'); + s.PutU4(v.size()); // number of elements + s.PutU4(0); // no encoding (1 would be zip-compressed) + s.PutU4(v.size() * 8); // data size + for (auto it = v.begin(); it != v.end(); ++it) { s.PutF8(*it); } + node.EndProperties(s, 1); + node.End(s, false); +} + +// convenience function to create and write a property node, +// holding a single property which is an array of values. +// does not copy the data, so is efficient for large arrays. +// TODO: optional zip compression! +void FBX::Node::WritePropertyNode( + const std::string& name, + const std::vector& v, + Assimp::StreamWriterLE& s +){ + Node node(name); + node.Begin(s); + s.PutU1('i'); + s.PutU4(v.size()); // number of elements + s.PutU4(0); // no encoding (1 would be zip-compressed) + s.PutU4(v.size() * 4); // data size + for (auto it = v.begin(); it != v.end(); ++it) { s.PutI4(*it); } + node.EndProperties(s, 1); + node.End(s, false); +} + + +#endif // ASSIMP_BUILD_NO_FBX_EXPORTER +#endif // ASSIMP_BUILD_NO_EXPORT diff --git a/code/FBXExportNode.h b/code/FBXExportNode.h new file mode 100644 index 000000000..edce8f700 --- /dev/null +++ b/code/FBXExportNode.h @@ -0,0 +1,197 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2018, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file FBXExportNode.h +* Declares the FBX::Node helper class for fbx export. +*/ +#ifndef AI_FBXEXPORTNODE_H_INC +#define AI_FBXEXPORTNODE_H_INC + +#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER + +#include "FBXExportProperty.h" + +#include // StreamWriterLE + +#include +#include + +namespace FBX { + class Node; +} + +class FBX::Node +{ +public: // public data members + // TODO: accessors + std::string name; // node name + std::vector properties; // node properties + std::vector children; // child nodes + +public: // constructors + Node() = default; + Node(const std::string& n) : name(n) {} + Node(const std::string& n, const FBX::Property &p) + : name(n) + { properties.push_back(p); } + Node(const std::string& n, const std::vector &pv) + : name(n), properties(pv) {} + +public: // functions to add properties or children + // add a single property to the node + template + void AddProperty(T value) { + properties.emplace_back(value); + } + + // convenience function to add multiple properties at once + template + void AddProperties(T value, More... more) { + properties.emplace_back(value); + AddProperties(more...); + } + void AddProperties() {} + + // add a child node directly + void AddChild(const Node& node) { children.push_back(node); } + + // convenience function to add a child node with a single property + template + void AddChild( + const std::string& name, + More... more + ) { + FBX::Node c(name); + c.AddProperties(more...); + children.push_back(c); + } + +public: // support specifically for dealing with Properties70 nodes + + // it really is simpler to make these all separate functions. + // the versions with 'A' suffixes are for animatable properties. + // those often follow a completely different format internally in FBX. + void AddP70int(const std::string& name, int32_t value); + void AddP70bool(const std::string& name, bool value); + void AddP70double(const std::string& name, double value); + void AddP70numberA(const std::string& name, double value); + void AddP70color(const std::string& name, double r, double g, double b); + void AddP70colorA(const std::string& name, double r, double g, double b); + void AddP70vector(const std::string& name, double x, double y, double z); + void AddP70vectorA(const std::string& name, double x, double y, double z); + void AddP70string(const std::string& name, const std::string& value); + void AddP70enum(const std::string& name, int32_t value); + void AddP70time(const std::string& name, int64_t value); + + // template for custom P70 nodes. + // anything that doesn't fit in the above can be created manually. + template + void AddP70( + const std::string& name, + const std::string& type, + const std::string& type2, + const std::string& flags, + More... more + ) { + Node n("P"); + n.AddProperties(name, type, type2, flags, more...); + AddChild(n); + } + +public: // member functions for writing data to a file or stream + + // write the full node as binary data to the given file or stream + void Dump(std::shared_ptr outfile); + void Dump(Assimp::StreamWriterLE &s); + + // these other functions are for writing data piece by piece. + // they must be used carefully. + // for usage examples see FBXExporter.cpp. + void Begin(Assimp::StreamWriterLE &s); + void DumpProperties(Assimp::StreamWriterLE& s); + void EndProperties(Assimp::StreamWriterLE &s); + void EndProperties(Assimp::StreamWriterLE &s, size_t num_properties); + void DumpChildren(Assimp::StreamWriterLE& s); + void End(Assimp::StreamWriterLE &s, bool has_children); + +private: // data used for binary dumps + size_t start_pos; // starting position in stream + size_t end_pos; // ending position in stream + size_t property_start; // starting position of property section + +public: // static member functions + + // convenience function to create a node with a single property, + // and write it to the stream. + template + static void WritePropertyNode( + const std::string& name, + const T value, + Assimp::StreamWriterLE& s + ) { + FBX::Property p(value); + FBX::Node node(name, p); + node.Dump(s); + } + + // convenience function to create and write a property node, + // holding a single property which is an array of values. + // does not copy the data, so is efficient for large arrays. + static void WritePropertyNode( + const std::string& name, + const std::vector& v, + Assimp::StreamWriterLE& s + ); + + // convenience function to create and write a property node, + // holding a single property which is an array of values. + // does not copy the data, so is efficient for large arrays. + static void WritePropertyNode( + const std::string& name, + const std::vector& v, + Assimp::StreamWriterLE& s + ); +}; + + +#endif // ASSIMP_BUILD_NO_FBX_EXPORTER + +#endif // AI_FBXEXPORTNODE_H_INC diff --git a/code/FBXExportProperty.cpp b/code/FBXExportProperty.cpp new file mode 100644 index 000000000..1beaa4d27 --- /dev/null +++ b/code/FBXExportProperty.cpp @@ -0,0 +1,201 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2018, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ +#ifndef ASSIMP_BUILD_NO_EXPORT +#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER + +#include "FBXExportProperty.h" + +#include // StreamWriterLE +#include // DeadlyExportError + +#include +#include +#include // stringstream + + +// constructors for single element properties + +FBX::Property::Property(bool v) + : type('C'), data(1) +{ + data = {uint8_t(v)}; +} + +FBX::Property::Property(int16_t v) : type('Y'), data(2) +{ + uint8_t* d = data.data(); + (reinterpret_cast(d))[0] = v; +} + +FBX::Property::Property(int32_t v) : type('I'), data(4) +{ + uint8_t* d = data.data(); + (reinterpret_cast(d))[0] = v; +} + +FBX::Property::Property(float v) : type('F'), data(4) +{ + uint8_t* d = data.data(); + (reinterpret_cast(d))[0] = v; +} + +FBX::Property::Property(double v) : type('D'), data(8) +{ + uint8_t* d = data.data(); + (reinterpret_cast(d))[0] = v; +} + +FBX::Property::Property(int64_t v) : type('L'), data(8) +{ + uint8_t* d = data.data(); + (reinterpret_cast(d))[0] = v; +} + + +// constructors for array-type properties + +FBX::Property::Property(const char* c, bool raw) + : Property(std::string(c), raw) +{} + +// strings can either be saved as "raw" (R) data, or "string" (S) data +FBX::Property::Property(const std::string& s, bool raw) + : type(raw ? 'R' : 'S'), data(s.size()) +{ + for (size_t i = 0; i < s.size(); ++i) { + data[i] = uint8_t(s[i]); + } +} + +FBX::Property::Property(const std::vector& r) + : type('R'), data(r) +{} + +FBX::Property::Property(const std::vector& va) + : type('i'), data(4*va.size()) +{ + int32_t* d = reinterpret_cast(data.data()); + for (size_t i = 0; i < va.size(); ++i) { d[i] = va[i]; } +} + +FBX::Property::Property(const std::vector& va) + : type('d'), data(8*va.size()) +{ + double* d = reinterpret_cast(data.data()); + for (size_t i = 0; i < va.size(); ++i) { d[i] = va[i]; } +} + +FBX::Property::Property(const aiMatrix4x4& vm) + : type('d'), data(8*16) +{ + double* d = reinterpret_cast(data.data()); + for (size_t c = 0; c < 4; ++c) { + for (size_t r = 0; r < 4; ++r) { + d[4*c+r] = vm[r][c]; + } + } +} + +// public member functions + +size_t FBX::Property::size() +{ + switch (type) { + case 'C': case 'Y': case 'I': case 'F': case 'D': case 'L': + return data.size() + 1; + case 'S': case 'R': + return data.size() + 5; + case 'i': case 'd': + return data.size() + 13; + default: + throw DeadlyExportError("Requested size on property of unknown type"); + } +} + +void FBX::Property::Dump(Assimp::StreamWriterLE &s) +{ + s.PutU1(type); + uint8_t* d; + size_t N; + switch (type) { + case 'C': s.PutU1(*(reinterpret_cast(data.data()))); return; + case 'Y': s.PutI2(*(reinterpret_cast(data.data()))); return; + case 'I': s.PutI4(*(reinterpret_cast(data.data()))); return; + case 'F': s.PutF4(*(reinterpret_cast(data.data()))); return; + case 'D': s.PutF8(*(reinterpret_cast(data.data()))); return; + case 'L': s.PutI8(*(reinterpret_cast(data.data()))); return; + case 'S': + case 'R': + s.PutU4(data.size()); + for (size_t i = 0; i < data.size(); ++i) { s.PutU1(data[i]); } + return; + case 'i': + N = data.size() / 4; + s.PutU4(N); // number of elements + s.PutU4(0); // no encoding (1 would be zip-compressed) + // TODO: compress if large? + s.PutU4(data.size()); // data size + d = data.data(); + for (size_t i = 0; i < N; ++i) { + s.PutI4((reinterpret_cast(d))[i]); + } + return; + case 'd': + N = data.size() / 8; + s.PutU4(N); // number of elements + s.PutU4(0); // no encoding (1 would be zip-compressed) + // TODO: compress if large? + s.PutU4(data.size()); // data size + d = data.data(); + for (size_t i = 0; i < N; ++i) { + s.PutF8((reinterpret_cast(d))[i]); + } + return; + default: + std::stringstream err; + err << "Tried to dump property with invalid type '"; + err << type << "'!"; + throw DeadlyExportError(err.str()); + } +} + +#endif // ASSIMP_BUILD_NO_FBX_EXPORTER +#endif // ASSIMP_BUILD_NO_EXPORT diff --git a/code/FBXExportProperty.h b/code/FBXExportProperty.h new file mode 100644 index 000000000..8920346a3 --- /dev/null +++ b/code/FBXExportProperty.h @@ -0,0 +1,123 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2018, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file FBXExportProperty.h +* Declares the FBX::Property helper class for fbx export. +*/ +#ifndef AI_FBXEXPORTPROPERTY_H_INC +#define AI_FBXEXPORTPROPERTY_H_INC + +#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER + + +#include // aiMatrix4x4 +#include // StreamWriterLE + +#include +#include +#include // is_void + +namespace FBX { + class Property; +} + +/** FBX::Property + * + * Holds a value of any of FBX's recognized types, + * each represented by a particular one-character code. + * C : 1-byte uint8, usually 0x00 or 0x01 to represent boolean false and true + * Y : 2-byte int16 + * I : 4-byte int32 + * F : 4-byte float + * D : 8-byte double + * L : 8-byte int64 + * i : array of int32 + * f : array of float + * d : array of double + * l : array of int64 + * b : array of 1-byte booleans (0x00 or 0x01) + * S : string (array of 1-byte char) + * R : raw data (array of bytes) + */ +class FBX::Property +{ +public: + // constructors for basic types. + // all explicit to avoid accidental typecasting + explicit Property(bool v); + // TODO: determine if there is actually a byte type, + // or if this always means . 'C' seems to imply , + // so possibly the above was intended to represent both. + explicit Property(int16_t v); + explicit Property(int32_t v); + explicit Property(float v); + explicit Property(double v); + explicit Property(int64_t v); + // strings can either be stored as 'R' (raw) or 'S' (string) type + explicit Property(const char* c, bool raw=false); + explicit Property(const std::string& s, bool raw=false); + explicit Property(const std::vector& r); + explicit Property(const std::vector& va); + explicit Property(const std::vector& va); + explicit Property(const aiMatrix4x4& vm); + + // this will catch any type not defined above, + // so that we don't accidentally convert something we don't want. + // for example (const char*) --> (bool)... seriously wtf C++ + template + explicit Property(T v) : type('X') { + static_assert(std::is_void::value, "TRIED TO CREATE FBX PROPERTY WITH UNSUPPORTED TYPE, CHECK YOUR PROPERTY INSTANTIATION"); + } // note: no line wrap so it appears verbatim on the compiler error + + // the size of this property node in a binary file, in bytes + size_t size(); + + // write this property node as binary data to the given stream + void Dump(Assimp::StreamWriterLE &s); + +private: + char type; + std::vector data; +}; + +#endif // ASSIMP_BUILD_NO_FBX_EXPORTER + +#endif // AI_FBXEXPORTPROPERTY_H_INC diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp new file mode 100644 index 000000000..d13c97f6b --- /dev/null +++ b/code/FBXExporter.cpp @@ -0,0 +1,2036 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2018, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ +#ifndef ASSIMP_BUILD_NO_EXPORT +#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER + +#include "FBXExporter.h" +#include "FBXExportNode.h" +#include "FBXExportProperty.h" +#include "FBXCommon.h" + +#include // aiGetVersion +#include +#include +#include +#include // StreamWriterLE +#include // DeadlyExportError +#include // aiTextureType +#include +#include + +// Header files, standard library. +#include // shared_ptr +#include +#include // stringstream +#include // localtime, tm_* +#include +#include +#include +#include // endl + +// RESOURCES: +// https://code.blender.org/2013/08/fbx-binary-file-format-specification/ +// https://wiki.blender.org/index.php/User:Mont29/Foundation/FBX_File_Structure + +constexpr double DEG = 360.0 / 6.283185307179586476925286766559; + +// some constants that we'll use for writing metadata +namespace FBX { + const std::string EXPORT_VERSION_STR = "7.4.0"; + const uint32_t EXPORT_VERSION_INT = 7400; // 7.4 == 2014/2015 + // FBX files have some hashed values that depend on the creation time field, + // but for now we don't actually know how to generate these. + // what we can do is set them to a known-working version. + // this is the data that Blender uses in their FBX export process. + const std::string GENERIC_CTIME = "1970-01-01 10:00:00:000"; + const std::string GENERIC_FILEID = + "\x28\xb3\x2a\xeb\xb6\x24\xcc\xc2\xbf\xc8\xb0\x2a\xa9\x2b\xfc\xf1"; + const std::string GENERIC_FOOTID = + "\xfa\xbc\xab\x09\xd0\xc8\xd4\x66\xb1\x76\xfb\x83\x1c\xf7\x26\x7e"; + const std::string FOOT_MAGIC = + "\xf8\x5a\x8c\x6a\xde\xf5\xd9\x7e\xec\xe9\x0c\xe3\x75\x8f\x29\x0b"; +} + +using namespace Assimp; +using namespace FBX; + +namespace Assimp { + + // --------------------------------------------------------------------- + // Worker function for exporting a scene to binary FBX. + // Prototyped and registered in Exporter.cpp + void ExportSceneFBX ( + const char* pFile, + IOSystem* pIOSystem, + const aiScene* pScene, + const ExportProperties* pProperties + ){ + // initialize the exporter + FBXExporter exporter(pScene, pProperties); + + // perform binary export + exporter.ExportBinary(pFile, pIOSystem); + } + + // --------------------------------------------------------------------- + // Worker function for exporting a scene to ASCII FBX. + // Prototyped and registered in Exporter.cpp + /*void ExportSceneFBXA ( + const char* pFile, + IOSystem* pIOSystem, + const aiScene* pScene, + const ExportProperties* pProperties + ){ + // initialize the exporter + FBXExporter exporter(pScene, pProperties); + + // perform ascii export + exporter.ExportAscii(pFile, pIOSystem); + }*/ // TODO + +} // end of namespace Assimp + +FBXExporter::FBXExporter ( + const aiScene* pScene, + const ExportProperties* pProperties +) + : mScene(pScene) + , mProperties(pProperties) +{ + // will probably need to determine UIDs, connections, etc here. + // basically anything that needs to be known + // before we start writing sections to the stream. +} + +void FBXExporter::ExportBinary ( + const char* pFile, + IOSystem* pIOSystem +){ + // remember that we're exporting in binary mode + binary = true; + + // open the indicated file for writing (in binary mode) + outfile.reset(pIOSystem->Open(pFile,"wb")); + if (!outfile) { + throw DeadlyExportError( + "could not open output .fbx file: " + std::string(pFile) + ); + } + + // first a binary-specific file header + WriteBinaryHeader(); + + // the rest of the file is in node entries. + // we have to serialize each entry before we write to the output, + // as the first thing we write is the byte offset of the _next_ entry. + // Either that or we can skip back to write the offset when we finish. + WriteAllNodes(); + + // finally we have a binary footer to the file + WriteBinaryFooter(); + + // explicitly release file pointer, + // so we don't have to rely on class destruction. + outfile.reset(); +} + +void FBXExporter::ExportAscii ( + const char* pFile, + IOSystem* pIOSystem +){ + // remember that we're exporting in ascii mode + binary = false; + + // open the indicated file for writing in text mode + outfile.reset(pIOSystem->Open(pFile,"wt")); + if (!outfile) { + throw DeadlyExportError( + "could not open output .fbx file: " + std::string(pFile) + ); + } + + // this isn't really necessary, + // but the Autodesk FBX SDK puts a similar comment at the top of the file. + // Theirs declares that the file copyright is owned by Autodesk... + std::stringstream head; + using std::endl; + head << "; FBX " << EXPORT_VERSION_STR << " project file" << endl; + head << "; Created by the Open Asset Import Library (Assimp)" << endl; + head << "; http://assimp.org" << endl; + head << "; -------------------------------------------------" << endl; + head << endl; + const std::string ascii_header = head.str(); + outfile->Write(ascii_header.c_str(), ascii_header.size(), 1); + + // write all the sections + WriteAllNodes(); + + // explicitly release file pointer, + // so we don't have to rely on class destruction. + outfile.reset(); +} + +void FBXExporter::WriteBinaryHeader() +{ + // first a specific sequence of 23 bytes, always the same + const char binary_header[24] = "Kaydara FBX Binary\x20\x20\x00\x1a\x00"; + outfile->Write(binary_header, 1, 23); + + // then FBX version number, "multiplied" by 1000, as little-endian uint32. + // so 7.3 becomes 7300 == 0x841C0000, 7.4 becomes 7400 == 0xE81C0000, etc + { + StreamWriterLE outstream(outfile); + outstream.PutU4(EXPORT_VERSION_INT); + } // StreamWriter destructor writes the data to the file + + // after this the node data starts immediately + // (probably with the FBXHEaderExtension node) +} + +void FBXExporter::WriteBinaryFooter() +{ + outfile->Write(NULL_RECORD.c_str(), NULL_RECORD.size(), 1); + + outfile->Write(GENERIC_FOOTID.c_str(), GENERIC_FOOTID.size(), 1); + for (size_t i = 0; i < 4; ++i) { + outfile->Write("\x00", 1, 1); + } + + // here some padding is added for alignment to 16 bytes. + // if already aligned, the full 16 bytes is added. + size_t pos = outfile->Tell(); + size_t pad = 16 - (pos % 16); + for (size_t i = 0; i < pad; ++i) { + outfile->Write("\x00", 1, 1); + } + + // now the file version again + { + StreamWriterLE outstream(outfile); + outstream.PutU4(EXPORT_VERSION_INT); + } // StreamWriter destructor writes the data to the file + + // and finally some binary footer added to all files + for (size_t i = 0; i < 120; ++i) { + outfile->Write("\x00", 1, 1); + } + outfile->Write(FOOT_MAGIC.c_str(), FOOT_MAGIC.size(), 1); +} + +void FBXExporter::WriteAllNodes () +{ + // header + // (and fileid, creation time, creator, if binary) + WriteHeaderExtension(); + + // global settings + WriteGlobalSettings(); + + // documents + WriteDocuments(); + + // references + WriteReferences(); + + // definitions + WriteDefinitions(); + + // objects + WriteObjects(); + + // connections + WriteConnections(); + + // WriteTakes? (deprecated since at least 2015 (fbx 7.4)) +} + +//FBXHeaderExtension top-level node +void FBXExporter::WriteHeaderExtension () +{ + FBX::Node n("FBXHeaderExtension"); + StreamWriterLE outstream(outfile); + + // begin node + n.Begin(outstream); + + // write properties + // (none) + + // finish properties + n.EndProperties(outstream, 0); + + // write child nodes + FBX::Node::WritePropertyNode( + "FBXHeaderVersion", int32_t(1003), outstream + ); + FBX::Node::WritePropertyNode( + "FBXVersion", int32_t(EXPORT_VERSION_INT), outstream + ); + FBX::Node::WritePropertyNode( + "EncryptionType", int32_t(0), outstream + ); + + FBX::Node CreationTimeStamp("CreationTimeStamp"); + time_t rawtime; + time(&rawtime); + struct tm * now = localtime(&rawtime); + CreationTimeStamp.AddChild("Version", int32_t(1000)); + CreationTimeStamp.AddChild("Year", int32_t(now->tm_year + 1900)); + CreationTimeStamp.AddChild("Month", int32_t(now->tm_mon + 1)); + CreationTimeStamp.AddChild("Day", int32_t(now->tm_mday)); + CreationTimeStamp.AddChild("Hour", int32_t(now->tm_hour)); + CreationTimeStamp.AddChild("Minute", int32_t(now->tm_min)); + CreationTimeStamp.AddChild("Second", int32_t(now->tm_sec)); + CreationTimeStamp.AddChild("Millisecond", int32_t(0)); + CreationTimeStamp.Dump(outstream); + + std::stringstream creator; + creator << "Open Asset Import Library (Assimp) " << aiGetVersionMajor() + << "." << aiGetVersionMinor() << "." << aiGetVersionRevision(); + FBX::Node::WritePropertyNode("Creator", creator.str(), outstream); + + FBX::Node sceneinfo("SceneInfo"); + //sceneinfo.AddProperty("GlobalInfo" + FBX::SEPARATOR + "SceneInfo"); + // not sure if any of this is actually needed, + // so just write an empty node for now. + sceneinfo.Dump(outstream); + + // finish node + n.End(outstream, true); + + // that's it for FBXHeaderExtension... + + // but binary files also need top-level FileID, CreationTime, Creator: + std::vector raw(GENERIC_FILEID.size()); + for (size_t i = 0; i < GENERIC_FILEID.size(); ++i) { + raw[i] = uint8_t(GENERIC_FILEID[i]); + } + FBX::Node::WritePropertyNode("FileId", raw, outstream); + FBX::Node::WritePropertyNode("CreationTime", GENERIC_CTIME, outstream); + FBX::Node::WritePropertyNode("Creator", creator.str(), outstream); +} + +void FBXExporter::WriteGlobalSettings () +{ + FBX::Node gs("GlobalSettings"); + gs.AddChild("Version", int32_t(1000)); + + FBX::Node p("Properties70"); + p.AddP70int("UpAxis", 1); + p.AddP70int("UpAxisSign", 1); + p.AddP70int("FrontAxis", 2); + p.AddP70int("FrontAxisSign", 1); + p.AddP70int("CoordAxis", 0); + p.AddP70int("CoordAxisSign", 1); + p.AddP70int("OriginalUpAxis", 1); + p.AddP70int("OriginalUpAxisSign", 1); + p.AddP70double("UnitScaleFactor", 1.0); + p.AddP70double("OriginalUnitScaleFactor", 1.0); + p.AddP70color("AmbientColor", 0.0, 0.0, 0.0); + p.AddP70string("DefaultCamera", "Producer Perspective"); + p.AddP70enum("TimeMode", 11); + p.AddP70enum("TimeProtocol", 2); + p.AddP70enum("SnapOnFrameMode", 0); + p.AddP70time("TimeSpanStart", 0); // TODO: animation support + p.AddP70time("TimeSpanStop", FBX::SECOND); // TODO: animation support + p.AddP70double("CustomFrameRate", -1.0); + p.AddP70("TimeMarker", "Compound", "", ""); // not sure what this is + p.AddP70int("CurrentTimeMarker", -1); + gs.AddChild(p); + + gs.Dump(outfile); +} + +void FBXExporter::WriteDocuments () +{ + // not sure what the use of multiple documents would be, + // or whether any end-application supports it + FBX::Node docs("Documents"); + docs.AddChild("Count", int32_t(1)); + FBX::Node doc("Document"); + + // generate uid + int64_t uid = generate_uid(); + doc.AddProperties(uid, "", "Scene"); + FBX::Node p("Properties70"); + p.AddP70("SourceObject", "object", "", ""); // what is this even for? + p.AddP70string("ActiveAnimStackName", ""); // should do this properly? + doc.AddChild(p); + + // UID for root node in scene heirarchy. + // always set to 0 in the case of a single document. + // not sure what happens if more than one document exists, + // but that won't matter to us as we're exporting a single scene. + doc.AddChild("RootNode", int64_t(0)); + + docs.AddChild(doc); + docs.Dump(outfile); +} + +void FBXExporter::WriteReferences () +{ + // always empty for now. + // not really sure what this is for. + FBX::Node n("References"); + n.Dump(outfile); +} + + +// --------------------------------------------------------------- +// some internal helper functions used for writing the definitions +// (before any actual data is written) +// --------------------------------------------------------------- + +size_t count_nodes(const aiNode* n) { + size_t count = 1; + for (size_t i = 0; i < n->mNumChildren; ++i) { + count += count_nodes(n->mChildren[i]); + } + return count; +} + +bool has_phong_mat(const aiScene* scene) +{ + // just search for any material with a shininess exponent + for (size_t i = 0; i < scene->mNumMaterials; ++i) { + aiMaterial* mat = scene->mMaterials[i]; + float shininess = 0; + mat->Get(AI_MATKEY_SHININESS, shininess); + if (shininess > 0) { + return true; + } + } + return false; +} + +size_t count_images(const aiScene* scene) { + std::unordered_set images; + aiString texpath; + for (size_t i = 0; i < scene->mNumMaterials; ++i) { + aiMaterial* mat = scene->mMaterials[i]; + for ( + size_t tt = aiTextureType_DIFFUSE; + tt < aiTextureType_UNKNOWN; + ++tt + ){ + const aiTextureType textype = static_cast(tt); + const size_t texcount = mat->GetTextureCount(textype); + for (size_t j = 0; j < texcount; ++j) { + mat->GetTexture(textype, j, &texpath); + images.insert(std::string(texpath.C_Str())); + } + } + } + //for (auto &s : images) { + // std::cout << "found image: " << s << std::endl; + //} + return images.size(); +} + +size_t count_textures(const aiScene* scene) { + size_t count = 0; + for (size_t i = 0; i < scene->mNumMaterials; ++i) { + aiMaterial* mat = scene->mMaterials[i]; + for ( + size_t tt = aiTextureType_DIFFUSE; + tt < aiTextureType_UNKNOWN; + ++tt + ){ + // TODO: handle layered textures + if (mat->GetTextureCount(static_cast(tt)) > 0) { + count += 1; + } + } + } + return count; +} + +size_t count_deformers(const aiScene* scene) { + size_t count = 0; + for (size_t i = 0; i < scene->mNumMeshes; ++i) { + const size_t n = scene->mMeshes[i]->mNumBones; + if (n) { + // 1 main deformer, 1 subdeformer per bone + count += n + 1; + } + } + return count; +} + +void FBXExporter::WriteDefinitions () +{ + // basically this is just bookkeeping: + // determining how many of each type of object there are + // and specifying the base properties to use when otherwise unspecified. + + // we need to count the objects + int32_t count; + int32_t total_count = 0; + + // and store them + std::vector object_nodes; + FBX::Node n, pt, p; + + // GlobalSettings + // this seems to always be here in Maya exports + n = FBX::Node("ObjectType", Property("GlobalSettings")); + count = 1; + n.AddChild("Count", count); + object_nodes.push_back(n); + total_count += count; + + // AnimationStack / FbxAnimStack + // this seems to always be here in Maya exports + count = 0; + if (count) { + n = FBX::Node("ObjectType", Property("AnimationStack")); + n.AddChild("Count", count); + pt = FBX::Node("PropertyTemplate", Property("FbxAnimStack")); + p = FBX::Node("Properties70"); + p.AddP70string("Description", ""); + p.AddP70time("LocalStart", 0); + p.AddP70time("LocalStop", 0); + p.AddP70time("ReferenceStart", 0); + p.AddP70time("ReferenceStop", 0); + pt.AddChild(p); + n.AddChild(pt); + object_nodes.push_back(n); + total_count += count; + } + + // AnimationLayer / FbxAnimLayer + // this seems to always be here in Maya exports + count = 0; + if (count) { + n = FBX::Node("ObjectType", Property("AnimationLayer")); + n.AddChild("Count", count); + pt = FBX::Node("PropertyTemplate", Property("FBXAnimLayer")); + p = FBX::Node("Properties70"); + p.AddP70("Weight", "Number", "", "A", double(100)); + p.AddP70bool("Mute", 0); + p.AddP70bool("Solo", 0); + p.AddP70bool("Lock", 0); + p.AddP70color("Color", 0.8, 0.8, 0.8); + p.AddP70("BlendMode", "enum", "", "", int32_t(0)); + p.AddP70("RotationAccumulationMode", "enum", "", "", int32_t(0)); + p.AddP70("ScaleAccumulationMode", "enum", "", "", int32_t(0)); + p.AddP70("BlendModeBypass", "ULongLong", "", "", int64_t(0)); + pt.AddChild(p); + n.AddChild(pt); + object_nodes.push_back(n); + total_count += count; + } + + // NodeAttribute + // this is completely absurd. + // there can only be one "NodeAttribute" template, + // but FbxSkeleton, FbxCamera, FbxLight all are "NodeAttributes". + // so if only one exists we should set the template for that, + // otherwise... we just pick one :/. + // the others have to set all their properties every instance, + // because there's no template. + count = 1; // TODO: select properly + if (count) { + // FbxSkeleton + n = FBX::Node("ObjectType", Property("NodeAttribute")); + n.AddChild("Count", count); + pt = FBX::Node("PropertyTemplate", Property("FbxSkeleton")); + p = FBX::Node("Properties70"); + p.AddP70color("Color", 0.8, 0.8, 0.8); + p.AddP70double("Size", 33.333333333333); + p.AddP70("LimbLength", "double", "Number", "H", double(1)); + // note: not sure what the "H" flag is for - hidden? + pt.AddChild(p); + n.AddChild(pt); + object_nodes.push_back(n); + total_count += count; + } + + // Model / FbxNode + // <~~ node heirarchy + count = count_nodes(mScene->mRootNode) - 1; // (not counting root node) + if (count) { + n = FBX::Node("ObjectType", Property("Model")); + n.AddChild("Count", count); + pt = FBX::Node("PropertyTemplate", Property("FbxNode")); + p = FBX::Node("Properties70"); + p.AddP70enum("QuaternionInterpolate", 0); + p.AddP70vector("RotationOffset", 0.0, 0.0, 0.0); + p.AddP70vector("RotationPivot", 0.0, 0.0, 0.0); + p.AddP70vector("ScalingOffset", 0.0, 0.0, 0.0); + p.AddP70vector("ScalingPivot", 0.0, 0.0, 0.0); + p.AddP70bool("TranslationActive", 0); + p.AddP70vector("TranslationMin", 0.0, 0.0, 0.0); + p.AddP70vector("TranslationMax", 0.0, 0.0, 0.0); + p.AddP70bool("TranslationMinX", 0); + p.AddP70bool("TranslationMinY", 0); + p.AddP70bool("TranslationMinZ", 0); + p.AddP70bool("TranslationMaxX", 0); + p.AddP70bool("TranslationMaxY", 0); + p.AddP70bool("TranslationMaxZ", 0); + p.AddP70enum("RotationOrder", 0); + p.AddP70bool("RotationSpaceForLimitOnly", 0); + p.AddP70double("RotationStiffnessX", 0.0); + p.AddP70double("RotationStiffnessY", 0.0); + p.AddP70double("RotationStiffnessZ", 0.0); + p.AddP70double("AxisLen", 10.0); + p.AddP70vector("PreRotation", 0.0, 0.0, 0.0); + p.AddP70vector("PostRotation", 0.0, 0.0, 0.0); + p.AddP70bool("RotationActive", 0); + p.AddP70vector("RotationMin", 0.0, 0.0, 0.0); + p.AddP70vector("RotationMax", 0.0, 0.0, 0.0); + p.AddP70bool("RotationMinX", 0); + p.AddP70bool("RotationMinY", 0); + p.AddP70bool("RotationMinZ", 0); + p.AddP70bool("RotationMaxX", 0); + p.AddP70bool("RotationMaxY", 0); + p.AddP70bool("RotationMaxZ", 0); + p.AddP70enum("InheritType", 0); + p.AddP70bool("ScalingActive", 0); + p.AddP70vector("ScalingMin", 0.0, 0.0, 0.0); + p.AddP70vector("ScalingMax", 1.0, 1.0, 1.0); + p.AddP70bool("ScalingMinX", 0); + p.AddP70bool("ScalingMinY", 0); + p.AddP70bool("ScalingMinZ", 0); + p.AddP70bool("ScalingMaxX", 0); + p.AddP70bool("ScalingMaxY", 0); + p.AddP70bool("ScalingMaxZ", 0); + p.AddP70vector("GeometricTranslation", 0.0, 0.0, 0.0); + p.AddP70vector("GeometricRotation", 0.0, 0.0, 0.0); + p.AddP70vector("GeometricScaling", 1.0, 1.0, 1.0); + p.AddP70double("MinDampRangeX", 0.0); + p.AddP70double("MinDampRangeY", 0.0); + p.AddP70double("MinDampRangeZ", 0.0); + p.AddP70double("MaxDampRangeX", 0.0); + p.AddP70double("MaxDampRangeY", 0.0); + p.AddP70double("MaxDampRangeZ", 0.0); + p.AddP70double("MinDampStrengthX", 0.0); + p.AddP70double("MinDampStrengthY", 0.0); + p.AddP70double("MinDampStrengthZ", 0.0); + p.AddP70double("MaxDampStrengthX", 0.0); + p.AddP70double("MaxDampStrengthY", 0.0); + p.AddP70double("MaxDampStrengthZ", 0.0); + p.AddP70double("PreferedAngleX", 0.0); + p.AddP70double("PreferedAngleY", 0.0); + p.AddP70double("PreferedAngleZ", 0.0); + p.AddP70("LookAtProperty", "object", "", ""); + p.AddP70("UpVectorProperty", "object", "", ""); + p.AddP70bool("Show", 1); + p.AddP70bool("NegativePercentShapeSupport", 1); + p.AddP70int("DefaultAttributeIndex", -1); + p.AddP70bool("Freeze", 0); + p.AddP70bool("LODBox", 0); + p.AddP70( + "Lcl Translation", "Lcl Translation", "", "A", + double(0), double(0), double(0) + ); + p.AddP70( + "Lcl Rotation", "Lcl Rotation", "", "A", + double(0), double(0), double(0) + ); + p.AddP70( + "Lcl Scaling", "Lcl Scaling", "", "A", + double(1), double(1), double(1) + ); + p.AddP70("Visibility", "Visibility", "", "A", double(1)); + p.AddP70( + "Visibility Inheritance", "Visibility Inheritance", "", "", + int32_t(1) + ); + pt.AddChild(p); + n.AddChild(pt); + object_nodes.push_back(n); + total_count += count; + } + + // Geometry / FbxMesh + // <~~ aiMesh + count = mScene->mNumMeshes; + if (count) { + n = FBX::Node("ObjectType", Property("Geometry")); + n.AddChild("Count", count); + pt = FBX::Node("PropertyTemplate", Property("FbxMesh")); + p = FBX::Node("Properties70"); + p.AddP70color("Color", 0, 0, 0); + p.AddP70vector("BBoxMin", 0, 0, 0); + p.AddP70vector("BBoxMax", 0, 0, 0); + p.AddP70bool("Primary Visibility", 1); + p.AddP70bool("Casts Shadows", 1); + p.AddP70bool("Receive Shadows", 1); + pt.AddChild(p); + n.AddChild(pt); + object_nodes.push_back(n); + total_count += count; + } + + // Material / FbxSurfacePhong, FbxSurfaceLambert, FbxSurfaceMaterial + // <~~ aiMaterial + // basically if there's any phong material this is defined as phong, + // and otherwise lambert. + // More complex materials cause a bare-bones FbxSurfaceMaterial definition + // and are treated specially, as they're not really supported by FBX. + // TODO: support Maya's Stingray PBS material + count = mScene->mNumMaterials; + if (count) { + bool has_phong = has_phong_mat(mScene); + n = FBX::Node("ObjectType", Property("Material")); + n.AddChild("Count", count); + pt = FBX::Node("PropertyTemplate"); + if (has_phong) { + pt.AddProperty("FbxSurfacePhong"); + } else { + pt.AddProperty("FbxSurfaceLambert"); + } + p = FBX::Node("Properties70"); + if (has_phong) { + p.AddP70string("ShadingModel", "Phong"); + } else { + p.AddP70string("ShadingModel", "Lambert"); + } + p.AddP70bool("MultiLayer", 0); + p.AddP70colorA("EmissiveColor", 0.0, 0.0, 0.0); + p.AddP70numberA("EmissiveFactor", 1.0); + p.AddP70colorA("AmbientColor", 0.2, 0.2, 0.2); + p.AddP70numberA("AmbientFactor", 1.0); + p.AddP70colorA("DiffuseColor", 0.8, 0.8, 0.8); + p.AddP70numberA("DiffuseFactor", 1.0); + p.AddP70vector("Bump", 0.0, 0.0, 0.0); + p.AddP70vector("NormalMap", 0.0, 0.0, 0.0); + p.AddP70double("BumpFactor", 1.0); + p.AddP70colorA("TransparentColor", 0.0, 0.0, 0.0); + p.AddP70numberA("TransparencyFactor", 0.0); + p.AddP70color("DisplacementColor", 0.0, 0.0, 0.0); + p.AddP70double("DisplacementFactor", 1.0); + p.AddP70color("VectorDisplacementColor", 0.0, 0.0, 0.0); + p.AddP70double("VectorDisplacementFactor", 1.0); + if (has_phong) { + p.AddP70colorA("SpecularColor", 0.2, 0.2, 0.2); + p.AddP70numberA("SpecularFactor", 1.0); + p.AddP70numberA("ShininessExponent", 20.0); + p.AddP70colorA("ReflectionColor", 0.0, 0.0, 0.0); + p.AddP70numberA("ReflectionFactor", 1.0); + } + pt.AddChild(p); + n.AddChild(pt); + object_nodes.push_back(n); + total_count += count; + } + + // Video / FbxVideo + // one for each image file. + count = count_images(mScene); + if (count) { + n = FBX::Node("ObjectType", Property("Video")); + n.AddChild("Count", count); + pt = FBX::Node("PropertyTemplate", Property("FbxVideo")); + p = FBX::Node("Properties70"); + p.AddP70bool("ImageSequence", 0); + p.AddP70int("ImageSequenceOffset", 0); + p.AddP70double("FrameRate", 0.0); + p.AddP70int("LastFrame", 0); + p.AddP70int("Width", 0); + p.AddP70int("Height", 0); + p.AddP70("Path", "KString", "XRefUrl", "", ""); + p.AddP70int("StartFrame", 0); + p.AddP70int("StopFrame", 0); + p.AddP70double("PlaySpeed", 0.0); + p.AddP70time("Offset", 0); + p.AddP70enum("InterlaceMode", 0); + p.AddP70bool("FreeRunning", 0); + p.AddP70bool("Loop", 0); + p.AddP70enum("AccessMode", 0); + pt.AddChild(p); + n.AddChild(pt); + object_nodes.push_back(n); + total_count += count; + } + + // Texture / FbxFileTexture + // <~~ aiTexture + count = count_textures(mScene); + if (count) { + n = FBX::Node("ObjectType", Property("Texture")); + n.AddChild("Count", count); + pt = FBX::Node("PropertyTemplate", Property("FbxFileTexture")); + p = FBX::Node("Properties70"); + p.AddP70enum("TextureTypeUse", 0); + p.AddP70numberA("Texture alpha", 1.0); + p.AddP70enum("CurrentMappingType", 0); + p.AddP70enum("WrapModeU", 0); + p.AddP70enum("WrapModeV", 0); + p.AddP70bool("UVSwap", 0); + p.AddP70bool("PremultiplyAlpha", 1); + p.AddP70vectorA("Translation", 0.0, 0.0, 0.0); + p.AddP70vectorA("Rotation", 0.0, 0.0, 0.0); + p.AddP70vectorA("Scaling", 1.0, 1.0, 1.0); + p.AddP70vector("TextureRotationPivot", 0.0, 0.0, 0.0); + p.AddP70vector("TextureScalingPivot", 0.0, 0.0, 0.0); + p.AddP70enum("CurrentTextureBlendMode", 1); + p.AddP70string("UVSet", "default"); + p.AddP70bool("UseMaterial", 0); + p.AddP70bool("UseMipMap", 0); + pt.AddChild(p); + n.AddChild(pt); + object_nodes.push_back(n); + total_count += count; + } + + // AnimationCurveNode / FbxAnimCurveNode + count = 0; + if (count) { + n = FBX::Node("ObjectType", Property("AnimationCurveNode")); + n.AddChild("Count", count); + pt = FBX::Node("PropertyTemplate", Property("FbxAnimCurveNode")); + p = FBX::Node("Properties70"); + p.AddP70("d", "Compound", "", ""); + pt.AddChild(p); + n.AddChild(pt); + object_nodes.push_back(n); + total_count += count; + } + + // Pose + count = 0; + for (size_t i = 0; i < mScene->mNumMeshes; ++i) { + aiMesh* mesh = mScene->mMeshes[i]; + if (mesh->HasBones()) { ++count; } + } + if (count) { + n = FBX::Node("ObjectType", Property("Pose")); + n.AddChild("Count", count); + object_nodes.push_back(n); + total_count += count; + } + + // Deformer + count = count_deformers(mScene); + if (count) { + n = FBX::Node("ObjectType", Property("Deformer")); + n.AddChild("Count", count); + object_nodes.push_back(n); + total_count += count; + } + + // (template) + count = 0; + if (count) { + n = FBX::Node("ObjectType", Property("")); + n.AddChild("Count", count); + pt = FBX::Node("PropertyTemplate", Property("")); + p = FBX::Node("Properties70"); + pt.AddChild(p); + n.AddChild(pt); + object_nodes.push_back(n); + total_count += count; + } + + // now write it all + FBX::Node defs("Definitions"); + defs.AddChild("Version", int32_t(100)); + defs.AddChild("Count", int32_t(total_count)); + for (auto &n : object_nodes) { defs.AddChild(n); } + defs.Dump(outfile); +} + + +// ------------------------------------------------------------------- +// some internal helper functions used for writing the objects section +// (which holds the actual data) +// ------------------------------------------------------------------- + +aiNode* get_node_for_mesh(unsigned int meshIndex, aiNode* node) +{ + for (size_t i = 0; i < node->mNumMeshes; ++i) { + if (node->mMeshes[i] == meshIndex) { + return node; + } + } + for (size_t i = 0; i < node->mNumChildren; ++i) { + aiNode* ret = get_node_for_mesh(meshIndex, node->mChildren[i]); + if (ret) { return ret; } + } + return nullptr; +} + +aiMatrix4x4 get_world_transform(const aiNode* node, const aiScene* scene) +{ + std::vector node_chain; + while (node != scene->mRootNode) { + node_chain.push_back(node); + node = node->mParent; + } + aiMatrix4x4 transform; + for (auto n = node_chain.rbegin(); n != node_chain.rend(); ++n) { + transform *= (*n)->mTransformation; + } + return transform; +} + + +void FBXExporter::WriteObjects () +{ + // numbers should match those given in definitions! make sure to check + StreamWriterLE outstream(outfile); + FBX::Node object_node("Objects"); + object_node.Begin(outstream); + object_node.EndProperties(outstream); + + // geometry (aiMesh) + mesh_uids.clear(); + for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) { + // it's all about this mesh + aiMesh* m = mScene->mMeshes[mi]; + + // start the node record + FBX::Node n("Geometry"); + int64_t uid = generate_uid(); + mesh_uids.push_back(uid); + n.AddProperty(uid); + n.AddProperty(FBX::SEPARATOR + "Geometry"); + n.AddProperty("Mesh"); + n.Begin(outstream); + n.DumpProperties(outstream); + n.EndProperties(outstream); + + // output vertex data - each vertex should be unique (probably) + std::vector flattened_vertices; + // index of original vertex in vertex data vector + std::vector vertex_indices; + // map of vertex value to its index in the data vector + std::map index_by_vertex_value; + size_t index = 0; + for (size_t vi = 0; vi < m->mNumVertices; ++vi) { + aiVector3D vtx = m->mVertices[vi]; + auto elem = index_by_vertex_value.find(vtx); + if (elem == index_by_vertex_value.end()) { + vertex_indices.push_back(index); + index_by_vertex_value[vtx] = index; + flattened_vertices.push_back(vtx[0]); + flattened_vertices.push_back(vtx[1]); + flattened_vertices.push_back(vtx[2]); + ++index; + } else { + vertex_indices.push_back(elem->second); + } + } + FBX::Node::WritePropertyNode( + "Vertices", flattened_vertices, outstream + ); + + // output polygon data as a flattened array of vertex indices. + // the last vertex index of each polygon is negated and - 1 + std::vector polygon_data; + for (size_t fi = 0; fi < m->mNumFaces; ++fi) { + const aiFace &f = m->mFaces[fi]; + for (size_t pvi = 0; pvi < f.mNumIndices - 1; ++pvi) { + polygon_data.push_back(vertex_indices[f.mIndices[pvi]]); + } + polygon_data.push_back( + -1 - vertex_indices[f.mIndices[f.mNumIndices-1]] + ); + } + FBX::Node::WritePropertyNode( + "PolygonVertexIndex", polygon_data, outstream + ); + + // here could be edges but they're insane. + // it's optional anyway, so let's ignore it. + + FBX::Node::WritePropertyNode( + "GeometryVersion", int32_t(124), outstream + ); + + // normals, if any + if (m->HasNormals()) { + FBX::Node normals("LayerElementNormal", Property(int32_t(0))); + normals.Begin(outstream); + normals.DumpProperties(outstream); + normals.EndProperties(outstream); + FBX::Node::WritePropertyNode("Version", int32_t(101), outstream); + FBX::Node::WritePropertyNode("Name", "", outstream); + FBX::Node::WritePropertyNode( + "MappingInformationType", "ByPolygonVertex", outstream + ); + // TODO: vertex-normals or indexed normals when appropriate + FBX::Node::WritePropertyNode( + "ReferenceInformationType", "Direct", outstream + ); + std::vector normal_data; + normal_data.reserve(3 * polygon_data.size()); + for (size_t fi = 0; fi < m->mNumFaces; ++fi) { + const aiFace &f = m->mFaces[fi]; + for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) { + const aiVector3D &n = m->mNormals[f.mIndices[pvi]]; + normal_data.push_back(n.x); + normal_data.push_back(n.y); + normal_data.push_back(n.z); + } + } + FBX::Node::WritePropertyNode("Normals", normal_data, outstream); + // note: version 102 has a NormalsW also... not sure what it is, + // so we can stick with version 101 for now. + normals.End(outstream, true); + } + + // uvs, if any + for (size_t uvi = 0; uvi < m->GetNumUVChannels(); ++uvi) { + if (m->mNumUVComponents[uvi] > 2) { + // FBX only supports 2-channel UV maps... + // or at least i'm not sure how to indicate a different number + std::stringstream err; + err << "Only 2-channel UV maps supported by FBX,"; + err << " but mesh " << mi; + if (m->mName.length) { + err << " (" << m->mName.C_Str() << ")"; + } + err << " UV map " << uvi; + err << " has " << m->mNumUVComponents[uvi]; + err << " components! Data will be preserved,"; + err << " but may be incorrectly interpreted on load."; + DefaultLogger::get()->warn(err.str()); + } + FBX::Node uv("LayerElementUV", Property(int32_t(uvi))); + uv.Begin(outstream); + uv.DumpProperties(outstream); + uv.EndProperties(outstream); + FBX::Node::WritePropertyNode("Version", int32_t(101), outstream); + // it doesn't seem like assimp keeps the uv map name, + // so just leave it blank. + FBX::Node::WritePropertyNode("Name", "", outstream); + FBX::Node::WritePropertyNode( + "MappingInformationType", "ByPolygonVertex", outstream + ); + FBX::Node::WritePropertyNode( + "ReferenceInformationType", "IndexToDirect", outstream + ); + + std::vector uv_data; + std::vector uv_indices; + std::map index_by_uv; + size_t index = 0; + for (size_t fi = 0; fi < m->mNumFaces; ++fi) { + const aiFace &f = m->mFaces[fi]; + for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) { + const aiVector3D &uv = + m->mTextureCoords[uvi][f.mIndices[pvi]]; + auto elem = index_by_uv.find(uv); + if (elem == index_by_uv.end()) { + index_by_uv[uv] = index; + uv_indices.push_back(index); + for (size_t x = 0; x < m->mNumUVComponents[uvi]; ++x) { + uv_data.push_back(uv[x]); + } + ++index; + } else { + uv_indices.push_back(elem->second); + } + } + } + FBX::Node::WritePropertyNode("UV", uv_data, outstream); + FBX::Node::WritePropertyNode("UVIndex", uv_indices, outstream); + uv.End(outstream, true); + } + + // i'm not really sure why this material section exists, + // as the material is linked via "Connections". + // it seems to always have the same "0" value. + FBX::Node mat("LayerElementMaterial", Property(int32_t(0))); + mat.AddChild("Version", int32_t(101)); + mat.AddChild("Name", ""); + mat.AddChild("MappingInformationType", "AllSame"); + mat.AddChild("ReferenceInformationType", "IndexToDirect"); + std::vector mat_indices = {0}; + mat.AddChild("Materials", mat_indices); + mat.Dump(outstream); + + // finally we have the layer specifications, + // which select the normals / UV set / etc to use. + // TODO: handle multiple uv sets correctly? + FBX::Node layer("Layer", Property(int32_t(0))); + layer.AddChild("Version", int32_t(100)); + FBX::Node le("LayerElement"); + le.AddChild("Type", "LayerElementNormal"); + le.AddChild("TypedIndex", int32_t(0)); + layer.AddChild(le); + le = FBX::Node("LayerElement"); + le.AddChild("Type", "LayerElementMaterial"); + le.AddChild("TypedIndex", int32_t(0)); + layer.AddChild(le); + le = FBX::Node("LayerElement"); + le.AddChild("Type", "LayerElementUV"); + le.AddChild("TypedIndex", int32_t(0)); + layer.AddChild(le); + layer.Dump(outstream); + + // finish the node record + n.End(outstream, true); + } + + // aiMaterial + material_uids.clear(); + for (size_t i = 0; i < mScene->mNumMaterials; ++i) { + // it's all about this material + aiMaterial* m = mScene->mMaterials[i]; + + // these are used to recieve material data + float f; aiColor3D c; + + // start the node record + FBX::Node n("Material"); + + int64_t uid = generate_uid(); + material_uids.push_back(uid); + n.AddProperty(uid); + + aiString name; + m->Get(AI_MATKEY_NAME, name); + n.AddProperty(name.C_Str() + FBX::SEPARATOR + "Material"); + + n.AddProperty(""); + + n.AddChild("Version", int32_t(102)); + f = 0; + m->Get(AI_MATKEY_SHININESS, f); + bool phong = (f > 0); + if (phong) { + n.AddChild("ShadingModel", "phong"); + } else { + n.AddChild("ShadingModel", "lambert"); + } + n.AddChild("MultiLayer", int32_t(0)); + + FBX::Node p("Properties70"); + + // materials exported using the FBX SDK have two sets of fields. + // there are the properties specified in the PropertyTemplate, + // which are those supported by the modernFBX SDK, + // and an extra set of properties with simpler names. + // The extra properties are a legacy material system from pre-2009. + // + // In the modern system, each property has "color" and "factor". + // Generally the interpretation of these seems to be + // that the colour is multiplied by the factor before use, + // but this is not always clear-cut. + // + // Usually assimp only stores the colour, + // so we can just leave the factors at the default "1.0". + + // first we can export the "standard" properties + if (m->Get(AI_MATKEY_COLOR_AMBIENT, c) == aiReturn_SUCCESS) { + p.AddP70colorA("AmbientColor", c.r, c.g, c.b); + //p.AddP70numberA("AmbientFactor", 1.0); + } + if (m->Get(AI_MATKEY_COLOR_DIFFUSE, c) == aiReturn_SUCCESS) { + p.AddP70colorA("DiffuseColor", c.r, c.g, c.b); + //p.AddP70numberA("DiffuseFactor", 1.0); + } + if (m->Get(AI_MATKEY_COLOR_TRANSPARENT, c) == aiReturn_SUCCESS) { + // "TransparentColor" / "TransparencyFactor"... + // thanks FBX, for your insightful interpretation of consistency + p.AddP70colorA("TransparentColor", c.r, c.g, c.b); + // TransparencyFactor defaults to 0.0, so set it to 1.0. + // note: Maya always sets this to 1.0, + // so we can't use it sensibly as "Opacity". + // In stead we rely on the legacy "Opacity" value, below. + // Blender also relies on "Opacity" not "TransparencyFactor", + // probably for a similar reason. + p.AddP70numberA("TransparencyFactor", 1.0); + } + if (m->Get(AI_MATKEY_COLOR_REFLECTIVE, c) == aiReturn_SUCCESS) { + p.AddP70colorA("ReflectionColor", c.r, c.g, c.b); + } + if (m->Get(AI_MATKEY_REFLECTIVITY, f) == aiReturn_SUCCESS) { + p.AddP70numberA("ReflectionFactor", f); + } + if (phong) { + if (m->Get(AI_MATKEY_COLOR_SPECULAR, c) == aiReturn_SUCCESS) { + p.AddP70colorA("SpecularColor", c.r, c.g, c.b); + } + if (m->Get(AI_MATKEY_SHININESS_STRENGTH, f) == aiReturn_SUCCESS) { + p.AddP70numberA("ShininessFactor", f); + } + if (m->Get(AI_MATKEY_SHININESS, f) == aiReturn_SUCCESS) { + p.AddP70numberA("ShininessExponent", f); + } + if (m->Get(AI_MATKEY_REFLECTIVITY, f) == aiReturn_SUCCESS) { + p.AddP70numberA("ReflectionFactor", f); + } + } + + // Now the legacy system. + // For safety let's include it. + // thrse values don't exist in the property template, + // and usualy are completely ignored when loading. + // One notable exception is the "Opacity" property, + // which Blender uses as (1.0 - alpha). + c.r = 0; c.g = 0; c.b = 0; + m->Get(AI_MATKEY_COLOR_EMISSIVE, c); + p.AddP70vector("Emissive", c.r, c.g, c.b); + c.r = 0.2; c.g = 0.2; c.b = 0.2; + m->Get(AI_MATKEY_COLOR_AMBIENT, c); + p.AddP70vector("Ambient", c.r, c.g, c.b); + c.r = 0.8; c.g = 0.8; c.b = 0.8; + m->Get(AI_MATKEY_COLOR_DIFFUSE, c); + p.AddP70vector("Diffuse", c.r, c.g, c.b); + // The FBX SDK determines "Opacity" from transparency colour (RGB) + // and factor (F) as: O = (1.0 - F * ((R + G + B) / 3)). + // However we actually have an opacity value, + // so we should take it from AI_MATKEY_OPACITY if possible. + // It might make more sense to use TransparencyFactor, + // but Blender actually loads "Opacity" correctly, so let's use it. + f = 1.0; + if (m->Get(AI_MATKEY_COLOR_TRANSPARENT, c) == aiReturn_SUCCESS) { + f = 1.0 - ((c.r + c.g + c.b) / 3); + } + m->Get(AI_MATKEY_OPACITY, f); + p.AddP70double("Opacity", f); + if (phong) { + // specular color is multiplied by shininess_strength + c.r = 0.2; c.g = 0.2; c.b = 0.2; + m->Get(AI_MATKEY_COLOR_SPECULAR, c); + f = 1.0; + m->Get(AI_MATKEY_SHININESS_STRENGTH, f); + p.AddP70vector("Specular", f*c.r, f*c.g, f*c.b); + f = 20.0; + m->Get(AI_MATKEY_SHININESS, f); + p.AddP70double("Shininess", f); + // Legacy "Reflectivity" is F*F*((R+G+B)/3), + // where F is the proportion of light reflected (AKA reflectivity), + // and RGB is the reflective colour of the material. + // No idea why, but we might as well set it the same way. + f = 0.0; + m->Get(AI_MATKEY_REFLECTIVITY, f); + c.r = 1.0, c.g = 1.0, c.b = 1.0; + m->Get(AI_MATKEY_COLOR_REFLECTIVE, c); + p.AddP70double("Reflectivity", f*f*((c.r+c.g+c.b)/3.0)); + } + + n.AddChild(p); + + n.Dump(outstream); + } + + // we need to look up all the images we're using, + // so we can generate uids, and eliminate duplicates. + std::map uid_by_image; + for (size_t i = 0; i < mScene->mNumMaterials; ++i) { + aiString texpath; + aiMaterial* mat = mScene->mMaterials[i]; + for ( + size_t tt = aiTextureType_DIFFUSE; + tt < aiTextureType_UNKNOWN; + ++tt + ){ + const aiTextureType textype = static_cast(tt); + const size_t texcount = mat->GetTextureCount(textype); + for (size_t j = 0; j < texcount; ++j) { + mat->GetTexture(textype, j, &texpath); + const std::string texstring = texpath.C_Str(); + auto elem = uid_by_image.find(texstring); + if (elem == uid_by_image.end()) { + uid_by_image[texstring] = generate_uid(); + } + } + } + } + + // FbxVideo - stores images used by textures. + for (const auto &it : uid_by_image) { + if (it.first.compare(0, 1, "*") == 0) { + // TODO: embedded textures + continue; + } + FBX::Node n("Video"); + const int64_t& uid = it.second; + const std::string name = ""; // TODO: ... name??? + n.AddProperties(uid, name + FBX::SEPARATOR + "Video", "Clip"); + n.AddChild("Type", "Clip"); + FBX::Node p("Properties70"); + // TODO: get full path... relative path... etc... ugh... + // for now just use the same path for everything, + // and hopefully one of them will work out. + const std::string& path = it.first; + p.AddP70("Path", "KString", "XRefUrl", "", path); + n.AddChild(p); + n.AddChild("UseMipMap", int32_t(0)); + n.AddChild("Filename", path); + n.AddChild("RelativeFilename", path); + n.Dump(outstream); + } + + // Textures + // referenced by material_index/texture_type pairs. + std::map,int64_t> texture_uids; + const std::map prop_name_by_tt = { + {aiTextureType_DIFFUSE, "DiffuseColor"}, + {aiTextureType_SPECULAR, "SpecularColor"}, + {aiTextureType_AMBIENT, "AmbientColor"}, + {aiTextureType_EMISSIVE, "EmissiveColor"}, + {aiTextureType_HEIGHT, "Bump"}, + {aiTextureType_NORMALS, "NormalMap"}, + {aiTextureType_SHININESS, "ShininessExponent"}, + {aiTextureType_OPACITY, "TransparentColor"}, + {aiTextureType_DISPLACEMENT, "DisplacementColor"}, + //{aiTextureType_LIGHTMAP, "???"}, + {aiTextureType_REFLECTION, "ReflectionColor"} + //{aiTextureType_UNKNOWN, ""} + }; + for (size_t i = 0; i < mScene->mNumMaterials; ++i) { + // textures are attached to materials + aiMaterial* mat = mScene->mMaterials[i]; + int64_t material_uid = material_uids[i]; + + for ( + size_t j = aiTextureType_DIFFUSE; + j < aiTextureType_UNKNOWN; + ++j + ) { + const aiTextureType tt = static_cast(j); + size_t n = mat->GetTextureCount(tt); + + if (n < 1) { // no texture of this type + continue; + } + + if (n > 1) { + // TODO: multilayer textures + std::stringstream err; + err << "Multilayer textures not supported (for now),"; + err << " skipping texture type " << j; + err << " of material " << i; + DefaultLogger::get()->warn(err.str()); + } + + // get image path for this (single-image) texture + aiString tpath; + if (mat->GetTexture(tt, 0, &tpath) != aiReturn_SUCCESS) { + std::stringstream err; + err << "Failed to get texture 0 for texture of type " << tt; + err << " on material " << i; + err << ", however GetTextureCount returned 1."; + throw DeadlyExportError(err.str()); + } + const std::string texture_path(tpath.C_Str()); + + // get connected image uid + auto elem = uid_by_image.find(texture_path); + if (elem == uid_by_image.end()) { + // this should never happen + std::stringstream err; + err << "Failed to find video element for texture with path"; + err << " \"" << texture_path << "\""; + err << ", type " << j << ", material " << i; + throw DeadlyExportError(err.str()); + } + const int64_t image_uid = elem->second; + + // get the name of the material property to connect to + auto elem2 = prop_name_by_tt.find(tt); + if (elem2 == prop_name_by_tt.end()) { + // don't know how to handle this type of texture, + // so skip it. + std::stringstream err; + err << "Not sure how to handle texture of type " << j; + err << " on material " << i; + err << ", skipping..."; + DefaultLogger::get()->warn(err.str()); + continue; + } + const std::string& prop_name = elem2->second; + + // generate a uid for this texture + const int64_t texture_uid = generate_uid(); + + // link the texture to the material + FBX::Node c("C"); + c.AddProperties("OP", texture_uid, material_uid, prop_name); + connections.push_back(c); + + // link the image data to the texture + c = FBX::Node("C"); + c.AddProperties("OO", image_uid, texture_uid); + connections.push_back(c); + + // now write the actual texture node + FBX::Node tnode("Texture"); + // TODO: some way to determine texture name? + const std::string texture_name = "" + FBX::SEPARATOR + "Texture"; + tnode.AddProperties(texture_uid, texture_name, ""); + // there really doesn't seem to be a better type than this: + tnode.AddChild("Type", "TextureVideoClip"); + tnode.AddChild("Version", int32_t(202)); + tnode.AddChild("TextureName", texture_name); + FBX::Node p("Properties70"); + p.AddP70enum("CurrentTextureBlendMode", 0); // TODO: verify + //p.AddP70string("UVSet", ""); // TODO: how should this work? + p.AddP70bool("UseMaterial", 1); + tnode.AddChild(p); + // can't easily detrmine which texture path will be correct, + // so just store what we have in every field. + // these being incorrect is a common problem with FBX anyway. + tnode.AddChild("FileName", texture_path); + tnode.AddChild("RelativeFilename", texture_path); + tnode.AddChild("ModelUVTranslation", double(0.0), double(0.0)); + tnode.AddChild("ModelUVScaling", double(1.0), double(1.0)); + tnode.AddChild("Texture_Alpha_Soutce", "None"); + tnode.AddChild( + "Cropping", int32_t(0), int32_t(0), int32_t(0), int32_t(0) + ); + tnode.Dump(outstream); + } + } + + // bones. + // + // output structure: + // subset of node heirarchy that are "skeleton", + // i.e. do not have meshes but only bones. + // but.. i'm not sure how anyone could guarantee that... + // + // input... + // well, for each mesh it has "bones", + // and the bone names correspond to nodes. + // of course we also need the parent nodes, + // as they give some of the transform........ + // + // well. we can assume a sane input, i suppose. + // + // so input is the bone node heirarchy, + // with an extra thing for the transformation of the MESH in BONE space. + // + // output is a set of bone nodes, + // a "bindpose" which indicates the default local transform of all bones, + // and a set of "deformers". + // each deformer is parented to a mesh geometry, + // and has one or more "subdeformer"s as children. + // each subdeformer has one bone node as a child, + // and represents the influence of that bone on the grandparent mesh. + // the subdeformer has a list of indices, and weights, + // with indices specifying vertex indices, + // and weights specifying the correspoding influence of this bone. + // it also has Transform and TransformLink elements, + // specifying the transform of the MESH in BONE space, + // and the transformation of the BONE in WORLD space, + // likely in the bindpose. + // + // the input bone structure is different but similar, + // storing the number of weights for this bone, + // and an array of (vertex index, weight) pairs. + // + // one sticky point is that the number of vertices may not match, + // because assimp splits vertices by normal, uv, etc. + + // first we should mark all the skeleton nodes, + // so that they can be treated as LimbNode in stead of Mesh or Null. + // at the same time we can build up a map of bone nodes. + std::unordered_set limbnodes; + std::map node_by_bone; + for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) { + const aiMesh* m = mScene->mMeshes[mi]; + for (size_t bi =0; bi < m->mNumBones; ++bi) { + const aiBone* b = m->mBones[bi]; + const std::string name(b->mName.C_Str()); + if (node_by_bone.count(name) > 0) { + // already processed, skip + continue; + } + aiNode* n = mScene->mRootNode->FindNode(b->mName); + if (!n) { + // this should never happen + std::stringstream err; + err << "Failed to find node for bone: \"" << name << "\""; + throw DeadlyExportError(err.str()); + } + node_by_bone[name] = n; + limbnodes.insert(n); + if (n == mScene->mRootNode) { continue; } + // mark all parent nodes as skeleton as well, + // up until we find the root node, + // or else the node containing the mesh, + // or else the parent of a node containig the mesh. + for ( + const aiNode* parent = n->mParent; + parent != mScene->mRootNode; + parent = parent->mParent + ) { + bool end = false; + for (size_t i = 0; i < parent->mNumMeshes; ++i) { + if (parent->mMeshes[i] == mi) { + end = true; + break; + } + } + for (size_t j = 0; j < parent->mNumChildren; ++j) { + aiNode* child = parent->mChildren[j]; + for (size_t i = 0; i < child->mNumMeshes; ++i) { + if (child->mMeshes[i] == mi) { + end = true; + break; + } + } + if (end) { break; } + } + if (end) { break; } + limbnodes.insert(parent); + } + } + } + + // we'll need the uids for the bone nodes, so generate them now + std::map bone_uids; + for (auto &bone : limbnodes) { + std::string bone_name(bone->mName.C_Str()); + aiNode* bone_node = mScene->mRootNode->FindNode(bone->mName); + if (!bone_node) { + throw DeadlyExportError("Couldn't find node for bone" + bone_name); + } + auto elem = node_uids.find(bone_node); + if (elem == node_uids.end()) { + int64_t uid = generate_uid(); + node_uids[bone_node] = uid; + bone_uids[bone_name] = uid; + } else { + bone_uids[bone_name] = elem->second; + } + } + + // now, for each aiMesh, we need to export a deformer, + // and for each aiBone a subdeformer, + // which should have all the skinning info. + // these will need to be connected properly to the mesh, + // and we can do that all now. + for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) { + const aiMesh* m = mScene->mMeshes[mi]; + if (!m->HasBones()) { + continue; + } + // make a deformer for this mesh + int64_t deformer_uid = generate_uid(); + FBX::Node dnode("Deformer"); + dnode.AddProperties(deformer_uid, FBX::SEPARATOR + "Deformer", "Skin"); + dnode.AddChild("Version", int32_t(101)); + // "acuracy"... this is not a typo.... + dnode.AddChild("Link_DeformAcuracy", double(50)); + dnode.AddChild("SkinningType", "Linear"); // TODO: other modes? + dnode.Dump(outstream); + + // connect it + FBX::Node c("C"); + c.AddProperties("OO", deformer_uid, mesh_uids[mi]); + connections.push_back(c); // TODO: emplace_back + + // we will be indexing by vertex... + // but there might be a different number of "vertices" + // between assimp and our output FBX. + // this code is cut-and-pasted from the geometry section above... + // ideally this should not be so. + // --- + // index of original vertex in vertex data vector + std::vector vertex_indices; + // map of vertex value to its index in the data vector + std::map index_by_vertex_value; + size_t index = 0; + for (size_t vi = 0; vi < m->mNumVertices; ++vi) { + aiVector3D vtx = m->mVertices[vi]; + auto elem = index_by_vertex_value.find(vtx); + if (elem == index_by_vertex_value.end()) { + vertex_indices.push_back(index); + index_by_vertex_value[vtx] = index; + ++index; + } else { + vertex_indices.push_back(elem->second); + } + } + + // first get this mesh's position in world space, + // as we'll need it for each subdeformer. + // + // ...of course taking the position of the MESH doesn't make sense, + // as it can be instanced to many nodes. + // All we can do is assume no instancing, + // and take the first node we find that contains the mesh. + // + // We could in stead take the transform from the bone's node, + // but there's no guarantee that the bone is in the bindpose, + // so this would be even less reliable. + aiNode* mesh_node = get_node_for_mesh(mi, mScene->mRootNode); + aiMatrix4x4 mesh_node_xform = get_world_transform(mesh_node, mScene); + + // now make a subdeformer for each bone + for (size_t bi =0; bi < m->mNumBones; ++bi) { + const aiBone* b = m->mBones[bi]; + const std::string name(b->mName.C_Str()); + const int64_t subdeformer_uid = generate_uid(); + FBX::Node sdnode("Deformer"); + sdnode.AddProperties( + subdeformer_uid, FBX::SEPARATOR + "SubDeformer", "Cluster" + ); + sdnode.AddChild("Version", int32_t(100)); + sdnode.AddChild("UserData", "", ""); + + // get indices and weights + std::vector subdef_indices; + std::vector subdef_weights; + int32_t last_index = -1; + for (size_t wi = 0; wi < b->mNumWeights; ++wi) { + int32_t vi = vertex_indices[b->mWeights[wi].mVertexId]; + if (vi == last_index) { + // only for vertices we exported to fbx + // TODO, FIXME: this assumes identically-located vertices + // will always deform in the same way. + // as assimp doesn't store a separate list of "positions", + // there's not much that can be done about this + // other than assuming that identical position means + // identical vertex. + continue; + } + subdef_indices.push_back(vi); + subdef_weights.push_back(b->mWeights[wi].mWeight); + last_index = vi; + } + // yes, "indexes" + sdnode.AddChild("Indexes", subdef_indices); + sdnode.AddChild("Weights", subdef_weights); + // transform is the transform of the mesh, but in bone space... + // which is exactly what assimp's mOffsetMatrix is, + // no matter what the assimp docs may say. + aiMatrix4x4 tr = b->mOffsetMatrix; + sdnode.AddChild("Transform", tr); + // transformlink should be the position of the bone in world space, + // in the bind pose. + // For now let's use the inverse of mOffsetMatrix, + // and the (assumedly static) mesh position in world space. + // TODO: find a better way of doing this? there aren't many options + tr = b->mOffsetMatrix; + tr.Inverse(); + tr *= mesh_node_xform; + sdnode.AddChild("TransformLink", tr); + + // done + sdnode.Dump(outstream); + + // lastly, connect to the parent deformer + c = FBX::Node("C"); + c.AddProperties("OO", subdeformer_uid, deformer_uid); + connections.push_back(c); // TODO: emplace_back + + // we also need to connect the limb node to the subdeformer. + c = FBX::Node("C"); + c.AddProperties("OO", bone_uids[name], subdeformer_uid); + connections.push_back(c); // TODO: emplace_back + } + + + } + + // BindPose + // + // This is a legacy system, which should be unnecessary. + // + // Somehow including it slows file loading by the official FBX SDK, + // and as it can reconstruct it from the deformers anyway, + // this is not currently included. + // + // The code is kept here in case it's useful in the future, + // but it's pretty much a hack anyway, + // as assimp doesn't store bindpose information for full skeletons. + // + /*for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) { + aiMesh* mesh = mScene->mMeshes[mi]; + if (! mesh->HasBones()) { continue; } + int64_t bindpose_uid = generate_uid(); + FBX::Node bpnode("Pose"); + bpnode.AddProperty(bindpose_uid); + // note: this uid is never linked or connected to anything. + bpnode.AddProperty(FBX::SEPARATOR + "Pose"); // blank name + bpnode.AddProperty("BindPose"); + + bpnode.AddChild("Type", "BindPose"); + bpnode.AddChild("Version", int32_t(100)); + + aiNode* mesh_node = get_node_for_mesh(mi, mScene->mRootNode); + + // next get the whole skeleton for this mesh. + // we need it all to define the bindpose section. + // the FBX SDK will complain if it's missing, + // and also if parents of used bones don't have a subdeformer. + // order shouldn't matter. + std::set skeleton; + for (size_t bi = 0; bi < mesh->mNumBones; ++bi) { + // bone node should have already been indexed + const aiBone* b = mesh->mBones[bi]; + const std::string bone_name(b->mName.C_Str()); + aiNode* parent = node_by_bone[bone_name]; + // insert all nodes down to the root or mesh node + while ( + parent + && parent != mScene->mRootNode + && parent != mesh_node + ) { + skeleton.insert(parent); + parent = parent->mParent; + } + } + + // number of pose nodes. includes one for the mesh itself. + bpnode.AddChild("NbPoseNodes", int32_t(1 + skeleton.size())); + + // the first pose node is always the mesh itself + FBX::Node pose("PoseNode"); + pose.AddChild("Node", mesh_uids[mi]); + aiMatrix4x4 mesh_node_xform = get_world_transform(mesh_node, mScene); + pose.AddChild("Matrix", mesh_node_xform); + bpnode.AddChild(pose); + + for (aiNode* bonenode : skeleton) { + // does this node have a uid yet? + int64_t node_uid; + auto node_uid_iter = node_uids.find(bonenode); + if (node_uid_iter != node_uids.end()) { + node_uid = node_uid_iter->second; + } else { + node_uid = generate_uid(); + node_uids[bonenode] = node_uid; + } + + // make a pose thingy + pose = FBX::Node("PoseNode"); + pose.AddChild("Node", node_uid); + aiMatrix4x4 node_xform = get_world_transform(bonenode, mScene); + pose.AddChild("Matrix", node_xform); + bpnode.AddChild(pose); + } + + // now write it + bpnode.Dump(outstream); + }*/ + + // TODO: cameras, lights + + // write nodes (i.e. model heirarchy) + // start at root node + WriteModelNodes( + outstream, mScene->mRootNode, 0, bone_uids + ); + + object_node.End(outstream, true); +} + +// convenience map of magic node name strings to FBX properties, +// including the expected type of transform. +const std::map> transform_types = { + {"Translation", {"Lcl Translation", 't'}}, + {"RotationOffset", {"RotationOffset", 't'}}, + {"RotationPivot", {"RotationPivot", 't'}}, + {"PreRotation", {"PreRotation", 'r'}}, + {"Rotation", {"Lcl Rotation", 'r'}}, + {"PostRotation", {"PostRotation", 'r'}}, + {"RotationPivotInverse", {"RotationPivotInverse", 'i'}}, + {"ScalingOffset", {"ScalingOffset", 't'}}, + {"ScalingPivot", {"ScalingPivot", 't'}}, + {"Scaling", {"Lcl Scaling", 's'}}, + {"ScalingPivotInverse", {"ScalingPivotInverse", 'i'}}, + {"GeometricScaling", {"GeometricScaling", 's'}}, + {"GeometricRotation", {"GeometricRotation", 'r'}}, + {"GeometricTranslation", {"GeometricTranslation", 't'}} +}; + +// write a single model node to the stream +void WriteModelNode( + StreamWriterLE& outstream, + const aiNode* node, + int64_t node_uid, + const std::string& type, + const std::vector>& transform_chain, + TransformInheritance inherit_type=TransformInheritance_RSrs +){ + const aiVector3D zero = {0, 0, 0}; + const aiVector3D one = {1, 1, 1}; + FBX::Node m("Model"); + std::string name = node->mName.C_Str() + FBX::SEPARATOR + "Model"; + m.AddProperties(node_uid, name, type); + m.AddChild("Version", int32_t(232)); + FBX::Node p("Properties70"); + p.AddP70bool("RotationActive", 1); + p.AddP70int("DefaultAttributeIndex", 0); + p.AddP70enum("InheritType", inherit_type); + if (transform_chain.empty()) { + // decompose 4x4 transform matrix into TRS + aiVector3D t, r, s; + node->mTransformation.Decompose(s, r, t); + if (t != zero) { + p.AddP70( + "Lcl Translation", "Lcl Translation", "", "A", + double(t.x), double(t.y), double(t.z) + ); + } + if (r != zero) { + p.AddP70( + "Lcl Rotation", "Lcl Rotation", "", "A", + double(DEG*r.x), double(DEG*r.y), double(DEG*r.z) + ); + } + if (s != one) { + p.AddP70( + "Lcl Scaling", "Lcl Scaling", "", "A", + double(s.x), double(s.y), double(s.z) + ); + } + } else { + // apply the transformation chain. + // these transformation elements are created when importing FBX, + // which has a complex transformation heirarchy for each node. + // as such we can bake the heirarchy back into the node on export. + for (auto &item : transform_chain) { + auto elem = transform_types.find(item.first); + if (elem == transform_types.end()) { + // then this is a bug + std::stringstream err; + err << "unrecognized FBX transformation type: "; + err << item.first; + throw DeadlyExportError(err.str()); + } + const std::string &name = elem->second.first; + const aiVector3D &v = item.second; + if (name.compare(0, 4, "Lcl ") == 0) { + // special handling for animatable properties + p.AddP70( + name, name, "", "A", + double(v.x), double(v.y), double(v.z) + ); + } else { + p.AddP70vector(name, v.x, v.y, v.z); + } + } + } + m.AddChild(p); + + // not sure what these are for, + // but they seem to be omnipresent + m.AddChild("Shading", Property(true)); + m.AddChild("Culling", Property("CullingOff")); + + m.Dump(outstream); +} + +// wrapper for WriteModelNodes to create and pass a blank transform chain +void FBXExporter::WriteModelNodes( + StreamWriterLE& s, + const aiNode* node, + int64_t parent_uid, + const std::map& bone_uids +) { + std::vector> chain; + WriteModelNodes(s, node, parent_uid, bone_uids, chain); +} + +void FBXExporter::WriteModelNodes( + StreamWriterLE& outstream, + const aiNode* node, + int64_t parent_uid, + const std::map& bone_uids, + std::vector>& transform_chain +) { + // first collapse any expanded transformation chains created by FBX import. + std::string node_name(node->mName.C_Str()); + if (node_name.find(MAGIC_NODE_TAG) != std::string::npos) { + if (node->mNumChildren != 1) { + // this should never happen + std::stringstream err; + err << "FBX transformation node should have exactly 1 child,"; + err << " but " << node->mNumChildren << " found"; + err << " on node \"" << node_name << "\"!"; + throw DeadlyExportError(err.str()); + } + aiNode* next_node = node->mChildren[0]; + auto pos = node_name.find(MAGIC_NODE_TAG) + MAGIC_NODE_TAG.size() + 1; + std::string type_name = node_name.substr(pos); + auto elem = transform_types.find(type_name); + if (elem == transform_types.end()) { + // then this is a bug and should be fixed + std::stringstream err; + err << "unrecognized FBX transformation node"; + err << " of type " << type_name << " in node " << node_name; + throw DeadlyExportError(err.str()); + } + aiVector3D t, r, s; + node->mTransformation.Decompose(s, r, t); + switch (elem->second.second) { + case 'i': // inverse + // we don't need to worry about the inverse matrices + break; + case 't': // translation + transform_chain.emplace_back(elem->first, t); + break; + case 'r': // rotation + r *= DEG; + transform_chain.emplace_back(elem->first, r); + break; + case 's': // scale + transform_chain.emplace_back(elem->first, s); + break; + default: + // this should never happen + std::stringstream err; + err << "unrecognized FBX transformation type code: "; + err << elem->second.second; + throw DeadlyExportError(err.str()); + } + // now just continue to the next node + WriteModelNodes( + outstream, next_node, parent_uid, bone_uids, transform_chain + ); + return; + } + + int64_t node_uid = 0; + // generate uid and connect to parent, if not the root node, + if (node != mScene->mRootNode) { + auto elem = node_uids.find(node); + if (elem != node_uids.end()) { + node_uid = elem->second; + } else { + node_uid = generate_uid(); + node_uids[node] = node_uid; + } + FBX::Node c("C"); + c.AddProperties("OO", node_uid, parent_uid); + connections.push_back(c); + } + + // what type of node is this? + if (node == mScene->mRootNode) { + // handled later + } else if (node->mNumMeshes == 1) { + // connect to child mesh, which should have been written previously + FBX::Node c("C"); + c.AddProperties("OO", mesh_uids[node->mMeshes[0]], node_uid); + connections.push_back(c); + // also connect to the material for the child mesh + c = FBX::Node("C"); + c.AddProperties( + "OO", + material_uids[mScene->mMeshes[node->mMeshes[0]]->mMaterialIndex], + node_uid + ); + connections.push_back(c); + // write model node + WriteModelNode(outstream, node, node_uid, "Mesh", transform_chain); + } else if (bone_uids.count(node_name)) { + WriteModelNode(outstream, node, node_uid, "LimbNode", transform_chain); + // we also need to write a nodeattribute to mark it as a skeleton + int64_t node_attribute_uid = generate_uid(); + FBX::Node na("NodeAttribute"); + na.AddProperties( + node_attribute_uid, FBX::SEPARATOR + "NodeAttribute", "LimbNode" + ); + na.AddChild("TypeFlags", Property("Skeleton")); + na.Dump(outstream); + // and connect them + FBX::Node c("C"); + c.AddProperties("OO", node_attribute_uid, node_uid); + connections.push_back(c); + } else { + // generate a null node so we can add children to it + WriteModelNode(outstream, node, node_uid, "Null", transform_chain); + } + + // if more than one child mesh, make nodes for each mesh + if (node->mNumMeshes > 1 || node == mScene->mRootNode) { + for (size_t i = 0; i < node->mNumMeshes; ++i) { + // make a new model node + int64_t new_node_uid = generate_uid(); + // connect to parent node + FBX::Node c("C"); + c.AddProperties("OO", new_node_uid, node_uid); + connections.push_back(c); + // connect to child mesh, which should have been written previously + c = FBX::Node("C"); + c.AddProperties("OO", mesh_uids[node->mMeshes[i]], new_node_uid); + connections.push_back(c); + // also connect to the material for the child mesh + c = FBX::Node("C"); + c.AddProperties( + "OO", + material_uids[ + mScene->mMeshes[node->mMeshes[i]]->mMaterialIndex + ], + new_node_uid + ); + connections.push_back(c); + // write model node + FBX::Node m("Model"); + // take name from mesh name, if it exists + std::string name = mScene->mMeshes[node->mMeshes[i]]->mName.C_Str(); + name += FBX::SEPARATOR + "Model"; + m.AddProperties(new_node_uid, name, "Mesh"); + m.AddChild("Version", int32_t(232)); + FBX::Node p("Properties70"); + p.AddP70enum("InheritType", 1); + m.AddChild(p); + m.Dump(outstream); + } + } + + // now recurse into children + for (size_t i = 0; i < node->mNumChildren; ++i) { + WriteModelNodes( + outstream, node->mChildren[i], node_uid, bone_uids + ); + } +} + +void FBXExporter::WriteConnections () +{ + // we should have completed the connection graph already, + // so basically just dump it here + FBX::Node conn("Connections"); + StreamWriterLE outstream(outfile); + conn.Begin(outstream); + for (auto &n : connections) { + n.Dump(outstream); + } + conn.End(outstream, !connections.empty()); + connections.clear(); +} + +#endif // ASSIMP_BUILD_NO_FBX_EXPORTER +#endif // ASSIMP_BUILD_NO_EXPORT diff --git a/code/FBXExporter.h b/code/FBXExporter.h new file mode 100644 index 000000000..39c04ffee --- /dev/null +++ b/code/FBXExporter.h @@ -0,0 +1,146 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2018, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file FBXExporter.h +* Declares the exporter class to write a scene to an fbx file +*/ +#ifndef AI_FBXEXPORTER_H_INC +#define AI_FBXEXPORTER_H_INC + +#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER + +#include "FBXExportNode.h" // FBX::Node + +#include +//#include +#include // StreamWriterLE +#include // DeadlyExportError + +#include +#include +#include // shared_ptr +#include // stringstream + +struct aiScene; +struct aiNode; +//struct aiMaterial; + +namespace Assimp +{ + class IOSystem; + class IOStream; + class ExportProperties; + + // --------------------------------------------------------------------- + /** Helper class to export a given scene to an FBX file. */ + // --------------------------------------------------------------------- + class FBXExporter + { + public: + /// Constructor for a specific scene to export + FBXExporter(const aiScene* pScene, const ExportProperties* pProperties); + + // call one of these methods to export + void ExportBinary(const char* pFile, IOSystem* pIOSystem); + void ExportAscii(const char* pFile, IOSystem* pIOSystem); + + private: + bool binary; // whether current export is in binary or ascii format + const aiScene* mScene; // the scene to export + const ExportProperties* mProperties; // currently unused + std::shared_ptr outfile; // file to write to + + std::vector connections; // conection storage + + std::vector mesh_uids; + std::vector material_uids; + std::map node_uids; + + // this crude unique-ID system is actually fine + int64_t last_uid = 999999; + int64_t generate_uid() { return ++last_uid; } + + // binary files have a specific header and footer, + // in addition to the actual data + void WriteBinaryHeader(); + void WriteBinaryFooter(); + + // WriteAllNodes does the actual export. + // It just calls all the Write
methods below in order. + void WriteAllNodes(); + + // Methods to write individual sections. + // The order here matches the order inside an FBX file. + // Each method corresponds to a top-level FBX section, + // except WriteHeader which also includes some binary-only sections + // and WriteFooter which is binary data only. + void WriteHeaderExtension(); + // WriteFileId(); // binary-only, included in WriteHeader + // WriteCreationTime(); // binary-only, included in WriteHeader + // WriteCreator(); // binary-only, included in WriteHeader + void WriteGlobalSettings(); + void WriteDocuments(); + void WriteReferences(); + void WriteDefinitions(); + void WriteObjects(); + void WriteConnections(); + // WriteTakes(); // deprecated since at least 2015 (fbx 7.4) + + // helpers + void WriteModelNodes( + Assimp::StreamWriterLE& s, + const aiNode* node, + int64_t parent_uid, + const std::map& bone_uids + ); + void WriteModelNodes( // usually don't call this directly + StreamWriterLE& s, + const aiNode* node, + int64_t parent_uid, + const std::map& bone_uids, + std::vector>& transform_chain + ); + }; +} + +#endif // ASSIMP_BUILD_NO_FBX_EXPORTER + +#endif // AI_FBXEXPORTER_H_INC From 95f66f84efb4abc52b110008154a8909853fbf34 Mon Sep 17 00:00:00 2001 From: Tommy Date: Mon, 19 Feb 2018 14:33:33 +0100 Subject: [PATCH 028/278] Remove constexpr for MSVC. --- code/FBXExporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index d13c97f6b..9cdb34f40 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -70,7 +70,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // https://code.blender.org/2013/08/fbx-binary-file-format-specification/ // https://wiki.blender.org/index.php/User:Mont29/Foundation/FBX_File_Structure -constexpr double DEG = 360.0 / 6.283185307179586476925286766559; +const double DEG = 57.29577951308232087679815481; // degrees per radian // some constants that we'll use for writing metadata namespace FBX { From 1de9b3232aa20bd532f284f8a9729a44fa31d147 Mon Sep 17 00:00:00 2001 From: Tommy Date: Mon, 19 Feb 2018 15:04:46 +0100 Subject: [PATCH 029/278] Silence a clang warning. --- code/FBXExporter.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index 9cdb34f40..86804bccc 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -147,6 +147,11 @@ void FBXExporter::ExportBinary ( // remember that we're exporting in binary mode binary = true; + // we're not currently using these preferences, + // but clang will cry about it if we never touch it. + // TODO: some of these might be relevant to export + (void)mProperties; + // open the indicated file for writing (in binary mode) outfile.reset(pIOSystem->Open(pFile,"wb")); if (!outfile) { From f0ccff70a4448f5888955eb5a6215f3cd2efe3ac Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 20 Feb 2018 09:03:18 +0100 Subject: [PATCH 030/278] Update FileSystemFilter.h Fix review findings --- code/FileSystemFilter.h | 117 +++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 63 deletions(-) diff --git a/code/FileSystemFilter.h b/code/FileSystemFilter.h index 0fabb41dd..668d79625 100644 --- a/code/FileSystemFilter.h +++ b/code/FileSystemFilter.h @@ -42,13 +42,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * Implements a filter system to filter calls to Exists() and Open() * in order to improve the success rate of file opening ... */ +#pragma once #ifndef AI_FILESYSTEMFILTER_H_INC #define AI_FILESYSTEMFILTER_H_INC -#include "../include/assimp/IOSystem.hpp" -#include "../include/assimp/DefaultLogger.hpp" -#include "../include/assimp/fast_atof.h" -#include "../include/assimp/ParsingUtils.h" +#include +#include +#include +#include namespace Assimp { @@ -64,90 +65,84 @@ class FileSystemFilter : public IOSystem public: /** Constructor. */ FileSystemFilter(const std::string& file, IOSystem* old) - : wrapped (old) - , src_file (file) - , sep(wrapped->getOsSeparator()) - { - ai_assert(NULL != wrapped); + : mWrapped (old) + , mSrc_file(file) + , sep(wrapped->getOsSeparator()) { + ai_assert(nullptr != mWrapped); // Determine base directory - base = src_file; + mBase = mSrc_file; std::string::size_type ss2; - if (std::string::npos != (ss2 = base.find_last_of("\\/"))) { - base.erase(ss2,base.length()-ss2); - } - else { - base = ""; - // return; + if (std::string::npos != (ss2 = mBase.find_last_of("\\/"))) { + mBase.erase(ss2,mBase.length()-ss2); + } else { + mBase = ""; } // make sure the directory is terminated properly char s; - if (base.length() == 0) { - base = "."; - base += getOsSeparator(); - } - else if ((s = *(base.end()-1)) != '\\' && s != '/') { - base += getOsSeparator(); + if ( mBase.empty() ) { + mBase = "."; + mBase += getOsSeparator(); + } else if ((s = *(base.end()-1)) != '\\' && s != '/') { + mBase += getOsSeparator(); } - DefaultLogger::get()->info("Import root directory is \'" + base + "\'"); + DefaultLogger::get()->info("Import root directory is \'" + mBase + "\'"); } /** Destructor. */ - ~FileSystemFilter() - { - // haha + ~FileSystemFilter() { + // empty } // ------------------------------------------------------------------- /** Tests for the existence of a file at the given path. */ - bool Exists( const char* pFile) const - { + bool Exists( const char* pFile) const { + ai_assert( nullptr != mWrapped ); std::string tmp = pFile; // Currently this IOSystem is also used to open THE ONE FILE. - if (tmp != src_file) { + if (tmp != mSrc_file) { BuildPath(tmp); Cleanup(tmp); } - return wrapped->Exists(tmp); + return mWrapped->Exists(tmp); } // ------------------------------------------------------------------- /** Returns the directory separator. */ - char getOsSeparator() const - { + char getOsSeparator() const { return sep; } // ------------------------------------------------------------------- /** Open a new file with a given path. */ - IOStream* Open( const char* pFile, const char* pMode = "rb") - { - ai_assert(pFile); - ai_assert(pMode); + IOStream* Open( const char* pFile, const char* pMode = "rb") { + ai_assert( nullptr != mWrapped ); + ai_assert( nullptr != pFile ); + ai_assert( nullptr != pMode ); // First try the unchanged path - IOStream* s = wrapped->Open(pFile,pMode); + IOStream* s = mWrapped->Open(pFile,pMode); - if (!s) { + if (nullptr == s) { std::string tmp = pFile; // Try to convert between absolute and relative paths BuildPath(tmp); - s = wrapped->Open(tmp,pMode); + s = mWrapped->Open(tmp,pMode); - if (!s) { + if (nullptr == s) { // Finally, look for typical issues with paths // and try to correct them. This is our last // resort. tmp = pFile; Cleanup(tmp); BuildPath(tmp); - s = wrapped->Open(tmp,pMode); + s = mWrapped->Open(tmp,pMode); } } @@ -156,27 +151,26 @@ public: // ------------------------------------------------------------------- /** Closes the given file and releases all resources associated with it. */ - void Close( IOStream* pFile) - { - return wrapped->Close(pFile); + void Close( IOStream* pFile) { + ai_assert( nullptr != mWrapped ); + return mWrapped->Close(pFile); } // ------------------------------------------------------------------- /** Compare two paths */ - bool ComparePaths (const char* one, const char* second) const - { - return wrapped->ComparePaths (one,second); + bool ComparePaths (const char* one, const char* second) const { + ai_assert( nullptr != mWrapped ); + return mWrapped->ComparePaths (one,second); } private: - // ------------------------------------------------------------------- /** Build a valid path from a given relative or absolute path. */ - void BuildPath (std::string& in) const - { + void BuildPath (std::string& in) const { + ai_assert( nullptr != mWrapped ); // if we can already access the file, great. - if (in.length() < 3 || wrapped->Exists(in)) { + if (in.length() < 3 || mWrapped->Exists(in)) { return; } @@ -184,8 +178,8 @@ private: if (in[1] != ':') { // append base path and try - const std::string tmp = base + in; - if (wrapped->Exists(tmp)) { + const std::string tmp = mBase + in; + if (mWrapped->Exists(tmp)) { in = tmp; return; } @@ -207,7 +201,7 @@ private: std::string::size_type last_dirsep = std::string::npos; while(true) { - tmp = base; + tmp = mBase; tmp += sep; std::string::size_type dirsep = in.rfind('/', last_dirsep); @@ -223,7 +217,7 @@ private: last_dirsep = dirsep-1; tmp += in.substr(dirsep+1, in.length()-pos); - if (wrapped->Exists(tmp)) { + if (mWrapped->Exists(tmp)) { in = tmp; return; } @@ -236,15 +230,14 @@ private: // ------------------------------------------------------------------- /** Cleanup the given path */ - void Cleanup (std::string& in) const - { - char last = 0; + void Cleanup (std::string& in) const { if(in.empty()) { return; } // Remove a very common issue when we're parsing file names: spaces at the // beginning of the path. + char last = 0; std::string::iterator it = in.begin(); while (IsSpaceOrNewLine( *it ))++it; if (it != in.begin()) { @@ -274,9 +267,7 @@ private: it = in.erase(it); --it; } - } - else if (*it == '%' && in.end() - it > 2) { - + } else if (*it == '%' && in.end() - it > 2) { // Hex sequence in URIs if( IsHex((&*it)[0]) && IsHex((&*it)[1]) ) { *it = HexOctetToDecimal(&*it); @@ -290,8 +281,8 @@ private: } private: - IOSystem* wrapped; - std::string src_file, base; + IOSystem *mWrapped; + std::string mSrc_file, mBase; char sep; }; From a92dbabc2538747620316ec1548e2ed64eb58d0a Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 20 Feb 2018 16:36:55 +0100 Subject: [PATCH 031/278] Update FileSystemFilter.h Fix missing save. --- code/FileSystemFilter.h | 45 +++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/code/FileSystemFilter.h b/code/FileSystemFilter.h index 464bb4c91..23d555eb8 100644 --- a/code/FileSystemFilter.h +++ b/code/FileSystemFilter.h @@ -67,7 +67,7 @@ public: FileSystemFilter(const std::string& file, IOSystem* old) : mWrapped (old) , mSrc_file(file) - , sep(wrapped->getOsSeparator()) { + , sep(mWrapped->getOsSeparator()) { ai_assert(nullptr != mWrapped); // Determine base directory @@ -101,6 +101,7 @@ public: /** Tests for the existence of a file at the given path. */ bool Exists( const char* pFile) const { ai_assert( nullptr != mWrapped ); + std::string tmp = pFile; // Currently this IOSystem is also used to open THE ONE FILE. @@ -165,51 +166,51 @@ public: // ------------------------------------------------------------------- /** Pushes a new directory onto the directory stack. */ - bool PushDirectory(const std::string &path) - { - return wrapped->PushDirectory(path); + bool PushDirectory(const std::string &path ) { + ai_assert( nullptr != mWrapped ); + return mWrapped->PushDirectory(path); } // ------------------------------------------------------------------- /** Returns the top directory from the stack. */ - const std::string &CurrentDirectory() const - { - return wrapped->CurrentDirectory(); + const std::string &CurrentDirectory() const { + ai_assert( nullptr != mWrapped ); + return mWrapped->CurrentDirectory(); } // ------------------------------------------------------------------- /** Returns the number of directories stored on the stack. */ - size_t StackSize() const - { - return wrapped->StackSize(); + size_t StackSize() const { + ai_assert( nullptr != mWrapped ); + return mWrapped->StackSize(); } // ------------------------------------------------------------------- /** Pops the top directory from the stack. */ - bool PopDirectory() - { - return wrapped->PopDirectory(); + bool PopDirectory() { + ai_assert( nullptr != mWrapped ); + return mWrapped->PopDirectory(); } // ------------------------------------------------------------------- /** Creates an new directory at the given path. */ - bool CreateDirectory(const std::string &path) - { - return wrapped->CreateDirectory(path); + bool CreateDirectory(const std::string &path) { + ai_assert( nullptr != mWrapped ); + return mWrapped->CreateDirectory(path); } // ------------------------------------------------------------------- /** Will change the current directory to the given path. */ - bool ChangeDirectory(const std::string &path) - { - return wrapped->ChangeDirectory(path); + bool ChangeDirectory(const std::string &path) { + ai_assert( nullptr != mWrapped ); + return mWrapped->ChangeDirectory(path); } // ------------------------------------------------------------------- /** Delete file. */ - bool DeleteFile(const std::string &file) - { - return wrapped->DeleteFile(file); + bool DeleteFile(const std::string &file) { + ai_assert( nullptr != mWrapped ); + return mWrapped->DeleteFile(file); } private: From 7cd1a66c8bc22a2c94460900f47c48d46be14bd1 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 20 Feb 2018 22:08:40 +0100 Subject: [PATCH 032/278] Use correct lookup. --- code/D3MFImporter.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index 29e27371e..5c036bf76 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -205,10 +205,11 @@ private: const std::string nodeName( xmlReader->getNodeName() ); if(xmlReader->getNodeName() == D3MF::XmlTag::triangle) { faces.push_back(ReadTriangle()); - } else if ( nodeName == D3MF::XmlTag::pid ) { - const std::string matId( xmlReader->getAttributeValue( nodeName.c_str() ) ); - int matIdx( std::atoi( matId.c_str() ) ); - mesh->mMaterialIndex = matIdx; + const char *pidToken( xmlReader->getAttributeValue( D3MF::XmlTag::pid.c_str() ) ); + if ( nullptr != pidToken ) { + int matIdx( std::atoi( pidToken ) ); + mesh->mMaterialIndex = matIdx; + } } } @@ -234,6 +235,7 @@ private: void ReadBaseMaterials() { while ( ReadToEndElement( D3MF::XmlTag::basematerials ) ) { mMaterials.push_back( readMaterialDef() ); + xmlReader->read(); } } @@ -324,8 +326,7 @@ private: return false; } - bool ReadToEndElement(const std::string& closeTag) - { + bool ReadToEndElement(const std::string& closeTag) { while(xmlReader->read()) { if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT) { From fb213e4bac445484d80bbde8888520ba83cfcf1f Mon Sep 17 00:00:00 2001 From: Tommy Date: Wed, 21 Feb 2018 12:23:28 +0100 Subject: [PATCH 033/278] FBX Importer: apply inverse of geometric transform to child nodes. --- code/FBXConverter.cpp | 66 +++++++++++++++++++++++++++++++++++++++---- code/FBXConverter.h | 7 +++-- 2 files changed, 66 insertions(+), 7 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 6929e5c33..7134bc2e0 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -142,6 +142,7 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa nodes.reserve( conns.size() ); std::vector nodes_chain; + std::vector post_nodes_chain; try { for( const Connection* con : conns ) { @@ -161,6 +162,7 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa if ( model ) { nodes_chain.clear(); + post_nodes_chain.clear(); aiMatrix4x4 new_abs_transform = parent_transform; @@ -168,7 +170,7 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa // assimp (or rather: the complicated transformation chain that // is employed by fbx) means that we may need multiple aiNode's // to represent a fbx node's transformation. - GenerateTransformationNodeChain( *model, nodes_chain ); + GenerateTransformationNodeChain( *model, nodes_chain, post_nodes_chain ); ai_assert( nodes_chain.size() ); @@ -213,8 +215,25 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa // attach geometry ConvertModel( *model, *nodes_chain.back(), new_abs_transform ); + // now link the geometric transform inverse nodes, + // before we attach any child nodes + for( aiNode* postnode : post_nodes_chain ) { + ai_assert( postnode ); + + if ( last_parent != &parent ) { + last_parent->mNumChildren = 1; + last_parent->mChildren = new aiNode*[ 1 ]; + last_parent->mChildren[ 0 ] = postnode; + } + + postnode->mParent = last_parent; + last_parent = postnode; + + new_abs_transform *= postnode->mTransformation; + } + // attach sub-nodes - ConvertNodes( model->ID(), *nodes_chain.back(), new_abs_transform ); + ConvertNodes( model->ID(), *last_parent, new_abs_transform ); if ( doc.Settings().readLights ) { ConvertLights( *model ); @@ -396,6 +415,12 @@ const char* Converter::NameTransformationComp( TransformationComp comp ) return "GeometricRotation"; case TransformationComp_GeometricTranslation: return "GeometricTranslation"; + case TransformationComp_GeometricScalingInverse: + return "GeometricScalingInverse"; + case TransformationComp_GeometricRotationInverse: + return "GeometricRotationInverse"; + case TransformationComp_GeometricTranslationInverse: + return "GeometricTranslationInverse"; case TransformationComp_MAXIMUM: // this is to silence compiler warnings default: break; @@ -437,6 +462,12 @@ const char* Converter::NameTransformationCompProperty( TransformationComp comp ) return "GeometricRotation"; case TransformationComp_GeometricTranslation: return "GeometricTranslation"; + case TransformationComp_GeometricScalingInverse: + return "GeometricScalingInverse"; + case TransformationComp_GeometricRotationInverse: + return "GeometricRotationInverse"; + case TransformationComp_GeometricTranslationInverse: + return "GeometricTranslationInverse"; case TransformationComp_MAXIMUM: // this is to silence compiler warnings break; } @@ -570,7 +601,7 @@ std::string Converter::NameTransformationChainNode( const std::string& name, Tra return name + std::string( MAGIC_NODE_TAG ) + "_" + NameTransformationComp( comp ); } -void Converter::GenerateTransformationNodeChain( const Model& model, std::vector& output_nodes ) +void Converter::GenerateTransformationNodeChain( const Model& model, std::vector& output_nodes, std::vector& post_output_nodes ) { const PropertyTable& props = model.Props(); const Model::RotOrder rot = model.RotationOrder(); @@ -646,16 +677,33 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector const aiVector3D& GeometricScaling = PropertyGet( props, "GeometricScaling", ok ); if ( ok && std::fabs( GeometricScaling.SquareLength() - 1.0f ) > zero_epsilon ) { aiMatrix4x4::Scaling( GeometricScaling, chain[ TransformationComp_GeometricScaling ] ); + aiVector3D GeometricScalingInverse = GeometricScaling; + bool canscale = true; + for (size_t i = 0; i < 3; ++i) { + if ( std::fabs( GeometricScalingInverse[i] ) > zero_epsilon ) { + GeometricScalingInverse[i] = 1.0f / GeometricScaling[i]; + } else { + FBXImporter::LogError( "cannot invert geometric scaling matrix with a 0.0 scale component" ); + canscale = false; + break; + } + } + if (canscale) { + aiMatrix4x4::Scaling( GeometricScalingInverse, chain[ TransformationComp_GeometricScalingInverse ] ); + } } const aiVector3D& GeometricRotation = PropertyGet( props, "GeometricRotation", ok ); if ( ok && GeometricRotation.SquareLength() > zero_epsilon ) { GetRotationMatrix( rot, GeometricRotation, chain[ TransformationComp_GeometricRotation ] ); + GetRotationMatrix( rot, GeometricRotation, chain[ TransformationComp_GeometricRotationInverse ] ); + chain[ TransformationComp_GeometricRotationInverse ].Inverse(); } const aiVector3D& GeometricTranslation = PropertyGet( props, "GeometricTranslation", ok ); if ( ok && GeometricTranslation.SquareLength() > zero_epsilon ) { aiMatrix4x4::Translation( GeometricTranslation, chain[ TransformationComp_GeometricTranslation ] ); + aiMatrix4x4::Translation( -GeometricTranslation, chain[ TransformationComp_GeometricTranslationInverse ] ); } // is_complex needs to be consistent with NeedsComplexTransformationChain() @@ -690,10 +738,18 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector } aiNode* nd = new aiNode(); - output_nodes.push_back( nd ); - nd->mName.Set( NameTransformationChainNode( name, comp ) ); nd->mTransformation = chain[ i ]; + + // geometric inverses go in a post-node chain + if ( comp == TransformationComp_GeometricScalingInverse || + comp == TransformationComp_GeometricRotationInverse || + comp == TransformationComp_GeometricTranslationInverse + ) { + post_output_nodes.push_back( nd ); + } else { + output_nodes.push_back( nd ); + } } ai_assert( output_nodes.size() ); diff --git a/code/FBXConverter.h b/code/FBXConverter.h index c882e9326..06a6f07a7 100644 --- a/code/FBXConverter.h +++ b/code/FBXConverter.h @@ -82,7 +82,10 @@ public: * The different parts that make up the final local transformation of a fbx-node */ enum TransformationComp { - TransformationComp_Translation = 0, + TransformationComp_GeometricScalingInverse = 0, + TransformationComp_GeometricRotationInverse, + TransformationComp_GeometricTranslationInverse, + TransformationComp_Translation, TransformationComp_RotationOffset, TransformationComp_RotationPivot, TransformationComp_PreRotation, @@ -153,7 +156,7 @@ private: /** * note: memory for output_nodes will be managed by the caller */ - void GenerateTransformationNodeChain(const Model& model, std::vector& output_nodes); + void GenerateTransformationNodeChain(const Model& model, std::vector& output_nodes, std::vector& post_output_nodes); // ------------------------------------------------------------------------------------------------ void SetupNodeMetadata(const Model& model, aiNode& nd); From a8fc22fd3f0dabc79820d074dd81f1c67d983dee Mon Sep 17 00:00:00 2001 From: Tommy Date: Wed, 21 Feb 2018 12:57:45 +0100 Subject: [PATCH 034/278] assimp_cmd: Add --verbose flag to 'info' command, to print node transforms. --- tools/assimp_cmd/Info.cpp | 49 +++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/tools/assimp_cmd/Info.cpp b/tools/assimp_cmd/Info.cpp index e19746db6..a9f66eb1f 100644 --- a/tools/assimp_cmd/Info.cpp +++ b/tools/assimp_cmd/Info.cpp @@ -47,9 +47,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Main.h" const char* AICMD_MSG_INFO_HELP_E = -"assimp info [-r]\n" +"assimp info [-r] [-v]\n" "\tPrint basic structure of a 3D model\n" -"\t-r,--raw: No postprocessing, do a raw import\n"; +"\t-r,--raw: No postprocessing, do a raw import\n" +"\t-v,--verbose: Print verbose info such as node transform data\n"; // ----------------------------------------------------------------------------------- @@ -184,7 +185,7 @@ std::string FindPTypes(const aiScene* scene) // ----------------------------------------------------------------------------------- void PrintHierarchy(const aiNode* root, unsigned int maxnest, unsigned int maxline, - unsigned int cline, unsigned int cnest=0) + unsigned int cline, bool verbose, unsigned int cnest=0) { if (cline++ >= maxline || cnest >= maxnest) { return; @@ -194,8 +195,29 @@ void PrintHierarchy(const aiNode* root, unsigned int maxnest, unsigned int maxli printf("-- "); } printf("\'%s\', meshes: %u\n",root->mName.data,root->mNumMeshes); + + if (verbose) { + // print the actual transform + //printf(","); + aiVector3D s, r, t; + root->mTransformation.Decompose(s, r, t); + if (s.x != 1.0 || s.y != 1.0 || s.z != 1.0) { + for(unsigned int i = 0; i < cnest; ++i) { printf(" "); } + printf(" S:[%f %f %f]\n", s.x, s.y, s.z); + } + if (r.x || r.y || r.z) { + for(unsigned int i = 0; i < cnest; ++i) { printf(" "); } + printf(" R:[%f %f %f]\n", r.x, r.y, r.z); + } + if (t.x || t.y || t.z) { + for(unsigned int i = 0; i < cnest; ++i) { printf(" "); } + printf(" T:[%f %f %f]\n", t.x, t.y, t.z); + } + } + //printf("\n"); + for (unsigned int i = 0; i < root->mNumChildren; ++i ) { - PrintHierarchy(root->mChildren[i],maxnest,maxline,cline,cnest+1); + PrintHierarchy(root->mChildren[i],maxnest,maxline,cline,verbose,cnest+1); if(i == root->mNumChildren-1) { for(unsigned int i = 0; i < cnest; ++i) { printf(" "); @@ -230,10 +252,23 @@ int Assimp_Info (const char* const* params, unsigned int num) const std::string in = std::string(params[0]); + // get -r and -v arguments + bool raw = false; + bool verbose = false; + for(unsigned int i = 1; i < num; ++i) { + if (!strcmp(params[i],"--raw")||!strcmp(params[i],"-r")) { + raw = true; + } + if (!strcmp(params[i],"--verbose")||!strcmp(params[i],"-v")) { + verbose = true; + } + } + // do maximum post-processing unless -r was specified ImportData import; - import.ppFlags = num>1&&(!strcmp(params[1],"--raw")||!strcmp(params[1],"-r")) ? 0 - : aiProcessPreset_TargetRealtime_MaxQuality; + if (!raw) { + import.ppFlags = aiProcessPreset_TargetRealtime_MaxQuality; + } // import the main model const aiScene* scene = ImportModel(import,in); @@ -346,7 +381,7 @@ int Assimp_Info (const char* const* params, unsigned int num) printf("\nNode hierarchy:\n"); unsigned int cline=0; - PrintHierarchy(scene->mRootNode,20,1000,cline); + PrintHierarchy(scene->mRootNode,20,1000,cline,verbose); printf("\n"); return 0; From 22dbb6c2d2bb8cf0a9e6495073a46434ba28dd34 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 21 Feb 2018 13:10:51 +0100 Subject: [PATCH 035/278] Update FileSystemFilter.h - Fix typo. -test in public metod against invalid parameters --- code/FileSystemFilter.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/code/FileSystemFilter.h b/code/FileSystemFilter.h index 23d555eb8..8d43c1c27 100644 --- a/code/FileSystemFilter.h +++ b/code/FileSystemFilter.h @@ -85,7 +85,7 @@ public: if ( mBase.empty() ) { mBase = "."; mBase += getOsSeparator(); - } else if ((s = *(base.end()-1)) != '\\' && s != '/') { + } else if ((s = *(mBase.end()-1)) != '\\' && s != '/') { mBase += getOsSeparator(); } @@ -123,6 +123,10 @@ public: /** Open a new file with a given path. */ IOStream* Open( const char* pFile, const char* pMode = "rb") { ai_assert( nullptr != mWrapped ); + if ( nullptr == pFile || nullptr == pMode ) { + return nullptr; + } + ai_assert( nullptr != pFile ); ai_assert( nullptr != pMode ); From c1f353f6c7673d5056d4ea07399e1de607b3838d Mon Sep 17 00:00:00 2001 From: Tommy Date: Wed, 21 Feb 2018 14:15:03 +0100 Subject: [PATCH 036/278] FBX Export: Geometric transformations always create transformation chain. In combination with fb213e4b, this fixes #1112. --- code/FBXConverter.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 7134bc2e0..893f9f405 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -582,8 +582,7 @@ bool Converter::NeedsComplexTransformationChain( const Model& model ) for ( size_t i = 0; i < TransformationComp_MAXIMUM; ++i ) { const TransformationComp comp = static_cast< TransformationComp >( i ); - if ( comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation || - comp == TransformationComp_GeometricScaling || comp == TransformationComp_GeometricRotation || comp == TransformationComp_GeometricTranslation ) { + if ( comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation ) { continue; } @@ -676,6 +675,7 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector const aiVector3D& GeometricScaling = PropertyGet( props, "GeometricScaling", ok ); if ( ok && std::fabs( GeometricScaling.SquareLength() - 1.0f ) > zero_epsilon ) { + is_complex = true; aiMatrix4x4::Scaling( GeometricScaling, chain[ TransformationComp_GeometricScaling ] ); aiVector3D GeometricScalingInverse = GeometricScaling; bool canscale = true; @@ -695,6 +695,7 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector const aiVector3D& GeometricRotation = PropertyGet( props, "GeometricRotation", ok ); if ( ok && GeometricRotation.SquareLength() > zero_epsilon ) { + is_complex = true; GetRotationMatrix( rot, GeometricRotation, chain[ TransformationComp_GeometricRotation ] ); GetRotationMatrix( rot, GeometricRotation, chain[ TransformationComp_GeometricRotationInverse ] ); chain[ TransformationComp_GeometricRotationInverse ].Inverse(); @@ -702,6 +703,7 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector const aiVector3D& GeometricTranslation = PropertyGet( props, "GeometricTranslation", ok ); if ( ok && GeometricTranslation.SquareLength() > zero_epsilon ) { + is_complex = true; aiMatrix4x4::Translation( GeometricTranslation, chain[ TransformationComp_GeometricTranslation ] ); aiMatrix4x4::Translation( -GeometricTranslation, chain[ TransformationComp_GeometricTranslationInverse ] ); } @@ -2265,8 +2267,7 @@ void Converter::GenerateNodeAnimations( std::vector& node_anims, has_any = true; - if ( comp != TransformationComp_Rotation && comp != TransformationComp_Scaling && comp != TransformationComp_Translation && - comp != TransformationComp_GeometricScaling && comp != TransformationComp_GeometricRotation && comp != TransformationComp_GeometricTranslation ) + if ( comp != TransformationComp_Rotation && comp != TransformationComp_Scaling && comp != TransformationComp_Translation ) { has_complex = true; } From f847d4817d3dc2542c33dfb07ad0402d9985e3d5 Mon Sep 17 00:00:00 2001 From: Tommy Date: Wed, 21 Feb 2018 15:29:57 +0100 Subject: [PATCH 037/278] FBX Export: fix logic for determining if scale transformation is identity. Previously it was comparing scale.SquareLength() to 1.0. --- code/FBXConverter.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 893f9f405..746777d65 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -579,6 +579,7 @@ bool Converter::NeedsComplexTransformationChain( const Model& model ) bool ok; const float zero_epsilon = 1e-6f; + const aiVector3D all_ones(1.0f, 1.0f, 1.0f); for ( size_t i = 0; i < TransformationComp_MAXIMUM; ++i ) { const TransformationComp comp = static_cast< TransformationComp >( i ); @@ -586,9 +587,17 @@ bool Converter::NeedsComplexTransformationChain( const Model& model ) continue; } + bool scale_compare = ( comp == TransformationComp_GeometricScaling || comp == TransformationComp_Scaling ); + const aiVector3D& v = PropertyGet( props, NameTransformationCompProperty( comp ), ok ); - if ( ok && v.SquareLength() > zero_epsilon ) { - return true; + if ( ok && scale_compare ) { + if ( (v - all_ones).SquareLength() > zero_epsilon ) { + return true; + } + } else if ( ok ) { + if ( v.SquareLength() > zero_epsilon ) { + return true; + } } } @@ -612,6 +621,7 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector // generate transformation matrices for all the different transformation components const float zero_epsilon = 1e-6f; + const aiVector3D all_ones(1.0f, 1.0f, 1.0f); bool is_complex = false; const aiVector3D& PreRotation = PropertyGet( props, "PreRotation", ok ); @@ -664,7 +674,7 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector } const aiVector3D& Scaling = PropertyGet( props, "Lcl Scaling", ok ); - if ( ok && std::fabs( Scaling.SquareLength() - 1.0f ) > zero_epsilon ) { + if ( ok && (Scaling - all_ones).SquareLength() > zero_epsilon ) { aiMatrix4x4::Scaling( Scaling, chain[ TransformationComp_Scaling ] ); } @@ -674,7 +684,7 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector } const aiVector3D& GeometricScaling = PropertyGet( props, "GeometricScaling", ok ); - if ( ok && std::fabs( GeometricScaling.SquareLength() - 1.0f ) > zero_epsilon ) { + if ( ok && (GeometricScaling - all_ones).SquareLength() > zero_epsilon ) { is_complex = true; aiMatrix4x4::Scaling( GeometricScaling, chain[ TransformationComp_GeometricScaling ] ); aiVector3D GeometricScalingInverse = GeometricScaling; From 1d901f075c8420a18ac291ab4b721d051b250911 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 23 Feb 2018 17:49:29 +0100 Subject: [PATCH 038/278] 3mf-importer: fix parsing of base-material color. --- code/3MFXmlTags.h | 3 ++ code/D3MFImporter.cpp | 88 ++++++++++++++++------------------- include/assimp/ParsingUtils.h | 27 +++++------ include/assimp/fast_atof.h | 4 +- 4 files changed, 60 insertions(+), 62 deletions(-) diff --git a/code/3MFXmlTags.h b/code/3MFXmlTags.h index 00938a45e..c4da2970d 100644 --- a/code/3MFXmlTags.h +++ b/code/3MFXmlTags.h @@ -45,6 +45,7 @@ namespace Assimp { namespace D3MF { namespace XmlTag { + // Model-data specific tags static const std::string model = "model"; static const std::string model_unit = "unit"; static const std::string metadata = "metadata"; @@ -63,6 +64,7 @@ namespace XmlTag { static const std::string v3 = "v3"; static const std::string id = "id"; static const std::string pid = "pid"; + static const std::string p1 = "p1"; static const std::string name = "name"; static const std::string type = "type"; static const std::string build = "build"; @@ -76,6 +78,7 @@ namespace XmlTag { static const std::string basematerials_name = "name"; static const std::string basematerials_displaycolor = "displaycolor"; + // Meta info tags static const std::string CONTENT_TYPES_ARCHIVE = "[Content_Types].xml"; static const std::string ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels"; static const std::string SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types"; diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index 5c036bf76..489926204 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -61,6 +61,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "3MFXmlTags.h" +#include + +#include namespace Assimp { namespace D3MF { @@ -175,10 +178,8 @@ private: void ImportVertices(aiMesh* mesh) { std::vector vertices; - while(ReadToEndElement(D3MF::XmlTag::vertices)) - { - if(xmlReader->getNodeName() == D3MF::XmlTag::vertex) - { + while(ReadToEndElement(D3MF::XmlTag::vertices)) { + if(xmlReader->getNodeName() == D3MF::XmlTag::vertex) { vertices.push_back(ReadVertex()); } } @@ -205,7 +206,7 @@ private: const std::string nodeName( xmlReader->getNodeName() ); if(xmlReader->getNodeName() == D3MF::XmlTag::triangle) { faces.push_back(ReadTriangle()); - const char *pidToken( xmlReader->getAttributeValue( D3MF::XmlTag::pid.c_str() ) ); + const char *pidToken( xmlReader->getAttributeValue( D3MF::XmlTag::p1.c_str() ) ); if ( nullptr != pidToken ) { int matIdx( std::atoi( pidToken ) ); mesh->mMaterialIndex = matIdx; @@ -253,92 +254,85 @@ private: if ( '#' != *buf ) { return false; } - - char comp[ 2 ] = { 0,0 }; - comp[ 0 ] = *buf; ++buf; - comp[ 1 ] = *buf; - ++buf; - diffuse.r = static_cast( std::atoi( comp ) ); + char comp[ 3 ] = { 0,0,'\0' }; comp[ 0 ] = *buf; ++buf; comp[ 1 ] = *buf; ++buf; - diffuse.g = static_cast( std::atoi( comp ) ); + diffuse.r = static_cast( strtol( comp, NULL, 16 ) ); + comp[ 0 ] = *buf; ++buf; comp[ 1 ] = *buf; ++buf; - diffuse.b = static_cast( std::atoi( comp ) ); + diffuse.g = static_cast< ai_real >( strtol( comp, NULL, 16 ) ); comp[ 0 ] = *buf; ++buf; comp[ 1 ] = *buf; ++buf; - diffuse.a = static_cast( std::atoi( comp ) ); + diffuse.b = static_cast< ai_real >( strtol( comp, NULL, 16 ) ); + + comp[ 0 ] = *buf; + ++buf; + comp[ 1 ] = *buf; + ++buf; + diffuse.a = static_cast< ai_real >( strtol( comp, NULL, 16 ) ); return true; } aiMaterial *readMaterialDef() { aiMaterial *mat( nullptr ); - //while ( ReadToEndElement( D3MF::XmlTag::basematerials_base ) ) { - const char *name( nullptr ); - const char *color( nullptr ); - const std::string nodeName( xmlReader->getNodeName() ); - if ( nodeName == D3MF::XmlTag::basematerials_base ) { - name = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_name.c_str() ); + const char *name( nullptr ); + const char *color( nullptr ); + const std::string nodeName( xmlReader->getNodeName() ); + if ( nodeName == D3MF::XmlTag::basematerials_base ) { + name = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_name.c_str() ); - aiString matName; - matName.Set( name ); - mat = new aiMaterial; - mat->AddProperty( &matName, AI_MATKEY_NAME ); + aiString matName; + matName.Set( name ); + mat = new aiMaterial; + mat->AddProperty( &matName, AI_MATKEY_NAME ); - color = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_displaycolor.c_str() ); - aiColor4D diffuse; - if ( parseColor( color, diffuse ) ) { - mat->AddProperty( &diffuse, 1, AI_MATKEY_COLOR_DIFFUSE ); - } + color = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_displaycolor.c_str() ); + aiColor4D diffuse; + if ( parseColor( color, diffuse ) ) { + mat->AddProperty( &diffuse, 1, AI_MATKEY_COLOR_DIFFUSE ); } - //} + } return mat; } private: - bool ReadToStartElement(const std::string& startTag) - { - while(xmlReader->read()) - { - if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT && xmlReader->getNodeName() == startTag) - { + bool ReadToStartElement(const std::string& startTag) { + while(xmlReader->read()) { + const std::string &nodeName( xmlReader->getNodeName() ); + if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT && nodeName == startTag) { return true; - } - else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END && - xmlReader->getNodeName() == startTag) - { + } else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END && nodeName == startTag) { return false; } } - //DefaultLogger::get()->error("unexpected EOF, expected closing <" + closeTag + "> tag"); + return false; } bool ReadToEndElement(const std::string& closeTag) { - while(xmlReader->read()) - { + while(xmlReader->read()) { + const std::string &nodeName( xmlReader->getNodeName() ); if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT) { return true; - } - else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END - && xmlReader->getNodeName() == closeTag) - { + } else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END && nodeName == closeTag) { return false; } } DefaultLogger::get()->error("unexpected EOF, expected closing <" + closeTag + "> tag"); + return false; } diff --git a/include/assimp/ParsingUtils.h b/include/assimp/ParsingUtils.h index 555b2a309..40e183a5c 100644 --- a/include/assimp/ParsingUtils.h +++ b/include/assimp/ParsingUtils.h @@ -66,49 +66,50 @@ static const unsigned int BufferSize = 4096; // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE char_t ToLower( char_t in) -{ +AI_FORCE_INLINE +char_t ToLower( char_t in ) { return (in >= (char_t)'A' && in <= (char_t)'Z') ? (char_t)(in+0x20) : in; } // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE char_t ToUpper( char_t in) { +AI_FORCE_INLINE +char_t ToUpper( char_t in) { return (in >= (char_t)'a' && in <= (char_t)'z') ? (char_t)(in-0x20) : in; } // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool IsUpper( char_t in) -{ +AI_FORCE_INLINE +bool IsUpper( char_t in) { return (in >= (char_t)'A' && in <= (char_t)'Z'); } // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool IsLower( char_t in) -{ +AI_FORCE_INLINE +bool IsLower( char_t in) { return (in >= (char_t)'a' && in <= (char_t)'z'); } // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool IsSpace( char_t in) -{ +AI_FORCE_INLINE +bool IsSpace( char_t in) { return (in == (char_t)' ' || in == (char_t)'\t'); } // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool IsLineEnd( char_t in) -{ +AI_FORCE_INLINE +bool IsLineEnd( char_t in) { return (in==(char_t)'\r'||in==(char_t)'\n'||in==(char_t)'\0'||in==(char_t)'\f'); } // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool IsSpaceOrNewLine( char_t in) -{ +AI_FORCE_INLINE +bool IsSpaceOrNewLine( char_t in) { return IsSpace(in) || IsLineEnd(in); } diff --git a/include/assimp/fast_atof.h b/include/assimp/fast_atof.h index 058a7ff87..fa70abfb2 100644 --- a/include/assimp/fast_atof.h +++ b/include/assimp/fast_atof.h @@ -129,8 +129,8 @@ inline unsigned int strtoul16( const char* in, const char** out=0) // Convert just one hex digit // Return value is UINT_MAX if the input character is not a hex digit. // ------------------------------------------------------------------------------------ -inline unsigned int HexDigitToDecimal(char in) -{ +inline +unsigned int HexDigitToDecimal(char in) { unsigned int out = UINT_MAX; if (in >= '0' && in <= '9') out = in - '0'; From 9c663e9630c5c38e8b8fc64b433b7d93b2594bf5 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 23 Feb 2018 18:14:46 +0100 Subject: [PATCH 039/278] fast_a_to_f: add some brackets. --- include/assimp/fast_atof.h | 92 ++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 48 deletions(-) diff --git a/include/assimp/fast_atof.h b/include/assimp/fast_atof.h index fa70abfb2..5c25db8e1 100644 --- a/include/assimp/fast_atof.h +++ b/include/assimp/fast_atof.h @@ -14,8 +14,8 @@ // ------------------------------------------------------------------------------------ -#ifndef __FAST_A_TO_F_H_INCLUDED__ -#define __FAST_A_TO_F_H_INCLUDED__ +#ifndef FAST_A_TO_F_H_INCLUDED +#define FAST_A_TO_F_H_INCLUDED #include #include @@ -148,8 +148,8 @@ unsigned int HexDigitToDecimal(char in) { // ------------------------------------------------------------------------------------ // Convert a hex-encoded octet (2 characters, i.e. df or 1a). // ------------------------------------------------------------------------------------ -inline uint8_t HexOctetToDecimal(const char* in) -{ +inline +uint8_t HexOctetToDecimal(const char* in) { return ((uint8_t)HexDigitToDecimal(in[0])<<4)+(uint8_t)HexDigitToDecimal(in[1]); } @@ -157,8 +157,8 @@ inline uint8_t HexOctetToDecimal(const char* in) // ------------------------------------------------------------------------------------ // signed variant of strtoul10 // ------------------------------------------------------------------------------------ -inline int strtol10( const char* in, const char** out=0) -{ +inline +int strtol10( const char* in, const char** out=0) { bool inv = (*in=='-'); if (inv || *in=='+') ++in; @@ -176,10 +176,9 @@ inline int strtol10( const char* in, const char** out=0) // 0NNN - oct // NNN - dec // ------------------------------------------------------------------------------------ -inline unsigned int strtoul_cppstyle( const char* in, const char** out=0) -{ - if ('0' == in[0]) - { +inline +unsigned int strtoul_cppstyle( const char* in, const char** out=0) { + if ('0' == in[0]) { return 'x' == in[1] ? strtoul16(in+2,out) : strtoul8(in+1,out); } return strtoul10(in, out); @@ -189,19 +188,20 @@ inline unsigned int strtoul_cppstyle( const char* in, const char** out=0) // Special version of the function, providing higher accuracy and safety // It is mainly used by fast_atof to prevent ugly and unwanted integer overflows. // ------------------------------------------------------------------------------------ -inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_inout=0) -{ +inline +uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_inout=0) { unsigned int cur = 0; uint64_t value = 0; - if ( *in < '0' || *in > '9' ) - throw std::invalid_argument(std::string("The string \"") + in + "\" cannot be converted into a value."); + if ( *in < '0' || *in > '9' ) { + throw std::invalid_argument( std::string( "The string \"" ) + in + "\" cannot be converted into a value." ); + } bool running = true; - while ( running ) - { - if ( *in < '0' || *in > '9' ) + while ( running ) { + if ( *in < '0' || *in > '9' ) { break; + } const uint64_t new_value = ( value * 10 ) + ( *in - '0' ); @@ -210,7 +210,6 @@ inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* DefaultLogger::get()->warn( std::string( "Converting the string \"" ) + in + "\" into a value resulted in overflow." ); return 0; } - //throw std::overflow_error(); value = new_value; @@ -218,21 +217,23 @@ inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* ++cur; if (max_inout && *max_inout == cur) { - if (out) { /* skip to end */ - while (*in >= '0' && *in <= '9') + while ( *in >= '0' && *in <= '9' ) { ++in; + } *out = in; } return value; } } - if (out) + if ( out ) { *out = in; + } - if (max_inout) + if ( max_inout ) { *max_inout = cur; + } return value; } @@ -240,11 +241,12 @@ inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* // ------------------------------------------------------------------------------------ // signed variant of strtoul10_64 // ------------------------------------------------------------------------------------ -inline int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* max_inout = 0) -{ +inline +int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* max_inout = 0) { bool inv = (*in == '-'); - if (inv || *in == '+') + if ( inv || *in == '+' ) { ++in; + } int64_t value = strtoul10_64(in, out, max_inout); if (inv) { @@ -253,7 +255,6 @@ inline int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* m return value; } - // Number of relevant decimals for floating-point parsing. #define AI_FAST_ATOF_RELAVANT_DECIMALS 15 @@ -263,8 +264,8 @@ inline int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* m // If you find any bugs, please send them to me, niko (at) irrlicht3d.org. // ------------------------------------------------------------------------------------ template -inline const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true) -{ +inline +const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true) { Real f = 0; bool inv = (*c == '-'); @@ -272,42 +273,36 @@ inline const char* fast_atoreal_move(const char* c, Real& out, bool check_comma ++c; } - if ((c[0] == 'N' || c[0] == 'n') && ASSIMP_strincmp(c, "nan", 3) == 0) - { + if ((c[0] == 'N' || c[0] == 'n') && ASSIMP_strincmp(c, "nan", 3) == 0) { out = std::numeric_limits::quiet_NaN(); c += 3; return c; } - if ((c[0] == 'I' || c[0] == 'i') && ASSIMP_strincmp(c, "inf", 3) == 0) - { + if ((c[0] == 'I' || c[0] == 'i') && ASSIMP_strincmp(c, "inf", 3) == 0) { out = std::numeric_limits::infinity(); if (inv) { out = -out; } c += 3; - if ((c[0] == 'I' || c[0] == 'i') && ASSIMP_strincmp(c, "inity", 5) == 0) - { + if ((c[0] == 'I' || c[0] == 'i') && ASSIMP_strincmp(c, "inity", 5) == 0) { c += 5; } return c; - } + if (!(c[0] >= '0' && c[0] <= '9') && - !((c[0] == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9')) - { + !((c[0] == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9')){ throw std::invalid_argument("Cannot parse string " "as real number: does not start with digit " "or decimal point followed by digit."); } - if (*c != '.' && (! check_comma || c[0] != ',')) - { + if (*c != '.' && (! check_comma || c[0] != ',')) { f = static_cast( strtoul10_64 ( c, &c) ); } - if ((*c == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9') - { + if ((*c == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9') { ++c; // NOTE: The original implementation is highly inaccurate here. The precision of a single @@ -358,24 +353,25 @@ inline const char* fast_atoreal_move(const char* c, Real& out, bool check_comma // ------------------------------------------------------------------------------------ // The same but more human. -inline ai_real fast_atof(const char* c) -{ +inline +ai_real fast_atof(const char* c) { ai_real ret(0.0); fast_atoreal_move(c, ret); + return ret; } -inline ai_real fast_atof( const char* c, const char** cout) -{ +inline +ai_real fast_atof( const char* c, const char** cout) { ai_real ret(0.0); *cout = fast_atoreal_move(c, ret); return ret; } -inline ai_real fast_atof( const char** inout) -{ +inline +ai_real fast_atof( const char** inout) { ai_real ret(0.0); *inout = fast_atoreal_move(*inout, ret); @@ -384,4 +380,4 @@ inline ai_real fast_atof( const char** inout) } // end of namespace Assimp -#endif +#endif // FAST_A_TO_F_H_INCLUDED From d00c4a54e6ae1a00131bc00682875017d5867c04 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 23 Feb 2018 18:59:38 +0100 Subject: [PATCH 040/278] Update fast_atof.h fix typo --- include/assimp/fast_atof.h | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/include/assimp/fast_atof.h b/include/assimp/fast_atof.h index 9c40a1646..fced5307a 100644 --- a/include/assimp/fast_atof.h +++ b/include/assimp/fast_atof.h @@ -26,15 +26,13 @@ #include "StringComparison.h" #include - #ifdef _MSC_VER # include #else # include #endif -namespace Assimp -{ +namespace Assimp { const double fast_atof_table[16] = { // we write [16] here instead of [] to work around a swig bug 0.0, @@ -64,8 +62,9 @@ unsigned int strtoul10( const char* in, const char** out=0) { unsigned int value = 0; for ( ;; ) { - if ( *in < '0' || *in > '9' ) + if ( *in < '0' || *in > '9' ) { break; + } value = ( value * 10 ) + ( *in - '0' ); ++in; @@ -109,8 +108,7 @@ unsigned int strtoul16( const char* in, const char** out=0) { value = ( value << 4u ) + ( *in - 'A' ) + 10; } else if (*in >= 'a' && *in <= 'f') { value = ( value << 4u ) + ( *in - 'a' ) + 10; - } - else { + } else { break; } ++in; @@ -258,7 +256,7 @@ int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* max_inou //! about 6 times faster than atof in win32. // If you find any bugs, please send them to me, niko (at) irrlicht3d.org. // ------------------------------------------------------------------------------------ -template +template inline const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true) { Real f = 0; @@ -284,10 +282,10 @@ const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true) c += 5; } return c; - + } if (!(c[0] >= '0' && c[0] <= '9') && - !((c[0] == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9')){ + !((c[0] == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9')) { throw std::invalid_argument("Cannot parse string " "as real number: does not start with digit " "or decimal point followed by digit."); @@ -322,7 +320,6 @@ const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true) // A major 'E' must be allowed. Necessary for proper reading of some DXF files. // Thanks to Zhao Lei to point out that this if() must be outside the if (*c == '.' ..) if (*c == 'e' || *c == 'E') { - ++c; const bool einv = (*c=='-'); if (einv || *c=='+') { From 375dd4c1793f9d4d0caa49d8a8b75994b6af0aa9 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 23 Feb 2018 20:34:34 +0100 Subject: [PATCH 041/278] Update D3MFImporter.cpp Fix order of init list. --- code/D3MFImporter.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index 489926204..fe5e260a4 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -71,9 +71,9 @@ namespace D3MF { class XmlSerializer { public: XmlSerializer(XmlReader* xmlReader) - : xmlReader(xmlReader) - , mMeshes() - , mMaterials() { + : mMeshes() + , mMaterials() + , xmlReader(xmlReader){ // empty } From b91976eead66c14633aa9d4dc803d27d55a54378 Mon Sep 17 00:00:00 2001 From: Tommy Date: Sat, 24 Feb 2018 08:42:03 +0100 Subject: [PATCH 042/278] FBX Export: handle newly-added geometric transform inverse nodes. This also tidies up the imported node structure a little, by not adding the inverse nodes if there are no child nodes. --- code/FBXConverter.cpp | 32 +++++++++++++++++++------------- code/FBXExporter.cpp | 5 ++++- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 746777d65..8aac70a0f 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -215,24 +215,30 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa // attach geometry ConvertModel( *model, *nodes_chain.back(), new_abs_transform ); - // now link the geometric transform inverse nodes, + // check if there will be any child nodes + const std::vector& child_conns + = doc.GetConnectionsByDestinationSequenced( model->ID(), "Model" ); + + // if so, link the geometric transform inverse nodes // before we attach any child nodes - for( aiNode* postnode : post_nodes_chain ) { - ai_assert( postnode ); + if (child_conns.size()) { + for( aiNode* postnode : post_nodes_chain ) { + ai_assert( postnode ); - if ( last_parent != &parent ) { - last_parent->mNumChildren = 1; - last_parent->mChildren = new aiNode*[ 1 ]; - last_parent->mChildren[ 0 ] = postnode; + if ( last_parent != &parent ) { + last_parent->mNumChildren = 1; + last_parent->mChildren = new aiNode*[ 1 ]; + last_parent->mChildren[ 0 ] = postnode; + } + + postnode->mParent = last_parent; + last_parent = postnode; + + new_abs_transform *= postnode->mTransformation; } - - postnode->mParent = last_parent; - last_parent = postnode; - - new_abs_transform *= postnode->mTransformation; } - // attach sub-nodes + // attach sub-nodes (if any) ConvertNodes( model->ID(), *last_parent, new_abs_transform ); if ( doc.Settings().readLights ) { diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index 86804bccc..582916d04 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -1775,7 +1775,10 @@ const std::map> transform_types = { {"ScalingPivotInverse", {"ScalingPivotInverse", 'i'}}, {"GeometricScaling", {"GeometricScaling", 's'}}, {"GeometricRotation", {"GeometricRotation", 'r'}}, - {"GeometricTranslation", {"GeometricTranslation", 't'}} + {"GeometricTranslation", {"GeometricTranslation", 't'}}, + {"GeometricTranslationInverse", {"GeometricTranslationInverse", 'i'}}, + {"GeometricRotationInverse", {"GeometricRotationInverse", 'i'}}, + {"GeometricScalingInverse", {"GeometricScalingInverse", 'i'}} }; // write a single model node to the stream From c18a07e47f514866c7b8cc57676611865de14415 Mon Sep 17 00:00:00 2001 From: Tommy Date: Sat, 24 Feb 2018 08:43:36 +0100 Subject: [PATCH 043/278] FBX Import: Properly clean up post_nodes_chain in case of exception. --- code/FBXConverter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 8aac70a0f..a948a7abf 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -265,6 +265,7 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa Util::delete_fun deleter; std::for_each( nodes.begin(), nodes.end(), deleter ); std::for_each( nodes_chain.begin(), nodes_chain.end(), deleter ); + std::for_each( post_nodes_chain.begin(), post_nodes_chain.end(), deleter ); } } From a9d70b2dbc620c52d6cbda53066c330e0c83125a Mon Sep 17 00:00:00 2001 From: Tommy Date: Sat, 24 Feb 2018 09:37:36 +0100 Subject: [PATCH 044/278] FBX Import: properly delete inverse geotrans nodes when not using them. --- code/FBXConverter.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index a948a7abf..5d732c7b2 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -236,6 +236,14 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa new_abs_transform *= postnode->mTransformation; } + } else { + // free the nodes we allocated as we don't need them + Util::delete_fun deleter; + std::for_each( + post_nodes_chain.begin(), + post_nodes_chain.end(), + deleter + ); } // attach sub-nodes (if any) From 4b7cd97fea9dc37f4b741840090c42c6a6a027ae Mon Sep 17 00:00:00 2001 From: Marco Di Benedetto Date: Sat, 24 Feb 2018 17:44:40 +0100 Subject: [PATCH 045/278] added support for embedded textures defined with buffer views. --- code/glTF2Asset.inl | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 520785081..cf43d67f1 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -669,7 +669,7 @@ inline Image::Image() } -inline void Image::Read(Value& obj, Asset& /*r*/) +inline void Image::Read(Value& obj, Asset& r) { if (!mDataLength) { if (Value* uri = FindString(obj, "uri")) { @@ -686,6 +686,18 @@ inline void Image::Read(Value& obj, Asset& /*r*/) this->uri = uristr; } } + else if (Value* bufferViewVal = FindUInt(obj, "bufferView")) { + this->bufferView = r.bufferViews.Retrieve(bufferViewVal->GetUint()); + Ref buffer = this->bufferView->buffer; + + this->mDataLength = this->bufferView->byteLength; + this->mData = new uint8_t [this->mDataLength]; + memcpy(this->mData, buffer->GetPointer(), this->mDataLength); + + if (Value* mtype = FindString(obj, "mimeType")) { + this->mimeType = mtype->GetString(); + } + } } } From 138b990d0a9e7833bec242517f448df8ee69e861 Mon Sep 17 00:00:00 2001 From: Marco Di Benedetto Date: Sat, 24 Feb 2018 17:57:42 +0100 Subject: [PATCH 046/278] added missing install of pbrmaterial.h --- code/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 6430187b0..6e2db91db 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -72,6 +72,7 @@ SET( PUBLIC_HEADERS ${HEADER_PATH}/matrix4x4.h ${HEADER_PATH}/matrix4x4.inl ${HEADER_PATH}/mesh.h + ${HEADER_PATH}/pbrmaterial.h ${HEADER_PATH}/postprocess.h ${HEADER_PATH}/quaternion.h ${HEADER_PATH}/quaternion.inl From 72e9f3ecb9bd12056d6992d87d3511546486df72 Mon Sep 17 00:00:00 2001 From: Marco Di Benedetto Date: Sat, 24 Feb 2018 18:47:43 +0100 Subject: [PATCH 047/278] fixed embedded texture reading. --- code/glTF2Asset.inl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index cf43d67f1..8f2b14e1a 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -691,8 +691,9 @@ inline void Image::Read(Value& obj, Asset& r) Ref buffer = this->bufferView->buffer; this->mDataLength = this->bufferView->byteLength; + // maybe this memcpy could be avoided if aiTexture does not delete[] pcData at destruction. this->mData = new uint8_t [this->mDataLength]; - memcpy(this->mData, buffer->GetPointer(), this->mDataLength); + memcpy(this->mData, buffer->GetPointer() + this->bufferView->byteOffset, this->mDataLength); if (Value* mtype = FindString(obj, "mimeType")) { this->mimeType = mtype->GetString(); From e7736022c8aae264011b7d097ae8338e29cebe47 Mon Sep 17 00:00:00 2001 From: Tommy Date: Sun, 25 Feb 2018 09:34:14 +0100 Subject: [PATCH 048/278] assimp_cmd info: list meshes and print basic mesh stats. --- tools/assimp_cmd/Info.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tools/assimp_cmd/Info.cpp b/tools/assimp_cmd/Info.cpp index a9f66eb1f..c4d5fe189 100644 --- a/tools/assimp_cmd/Info.cpp +++ b/tools/assimp_cmd/Info.cpp @@ -329,6 +329,29 @@ int Assimp_Info (const char* const* params, unsigned int num) special_points[2][0],special_points[2][1],special_points[2][2] ) ; + + // meshes + if (scene->mNumMeshes) { + printf("\nMeshes: (name) [vertices / bones / faces | primitive_types]\n"); + } + for (unsigned int i = 0; i < scene->mNumMeshes; ++i) { + const aiMesh* mesh = scene->mMeshes[i]; + printf(" %d (%s)", i, mesh->mName.C_Str()); + printf( + ": [%d / %d / %d |", + mesh->mNumVertices, + mesh->mNumBones, + mesh->mNumFaces + ); + const unsigned int ptypes = mesh->mPrimitiveTypes; + if (ptypes & aiPrimitiveType_POINT) { printf(" point"); } + if (ptypes & aiPrimitiveType_LINE) { printf(" line"); } + if (ptypes & aiPrimitiveType_TRIANGLE) { printf(" triangle"); } + if (ptypes & aiPrimitiveType_POLYGON) { printf(" polygon"); } + printf("]\n"); + } + + // materials unsigned int total=0; for(unsigned int i = 0;i < scene->mNumMaterials; ++i) { aiString name; @@ -340,6 +363,7 @@ int Assimp_Info (const char* const* params, unsigned int num) printf("\n"); } + // textures total=0; for(unsigned int i = 0;i < scene->mNumMaterials; ++i) { aiString name; @@ -369,6 +393,7 @@ int Assimp_Info (const char* const* params, unsigned int num) printf("\n"); } + // animations total=0; for(unsigned int i = 0;i < scene->mNumAnimations; ++i) { if (scene->mAnimations[i]->mName.length) { @@ -379,6 +404,7 @@ int Assimp_Info (const char* const* params, unsigned int num) printf("\n"); } + // node hierarchy printf("\nNode hierarchy:\n"); unsigned int cline=0; PrintHierarchy(scene->mRootNode,20,1000,cline,verbose); From 249f1844aee94af7d73e4c1c06ad1dd3da806536 Mon Sep 17 00:00:00 2001 From: Tommy Date: Thu, 22 Feb 2018 11:06:29 +0100 Subject: [PATCH 049/278] FBX Export: reconstruct full skeleton for any FBX deformers. --- code/FBXExporter.cpp | 201 ++++++++++++++++++++++++++----------------- code/FBXExporter.h | 5 +- 2 files changed, 126 insertions(+), 80 deletions(-) diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index 582916d04..6273f1977 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -1463,46 +1463,67 @@ void FBXExporter::WriteObjects () // one sticky point is that the number of vertices may not match, // because assimp splits vertices by normal, uv, etc. - // first we should mark all the skeleton nodes, - // so that they can be treated as LimbNode in stead of Mesh or Null. - // at the same time we can build up a map of bone nodes. + // first we should mark the skeleton for each mesh. + // the skeleton must include not only the aiBones, + // but also all their parent nodes. + // anything that affects the position of any bone node must be included. + std::vector> skeleton_by_mesh(mScene->mNumMeshes); + // at the same time we can build a list of all the skeleton nodes, + // which will be used later to mark them as type "limbNode". std::unordered_set limbnodes; + // and a map of nodes by bone name, as finding them is annoying. std::map node_by_bone; for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) { const aiMesh* m = mScene->mMeshes[mi]; + std::set skeleton; for (size_t bi =0; bi < m->mNumBones; ++bi) { const aiBone* b = m->mBones[bi]; const std::string name(b->mName.C_Str()); - if (node_by_bone.count(name) > 0) { - // already processed, skip - continue; + auto elem = node_by_bone.find(name); + aiNode* n; + if (elem != node_by_bone.end()) { + n = elem->second; + } else { + n = mScene->mRootNode->FindNode(b->mName); + if (!n) { + // this should never happen + std::stringstream err; + err << "Failed to find node for bone: \"" << name << "\""; + throw DeadlyExportError(err.str()); + } + node_by_bone[name] = n; + limbnodes.insert(n); } - aiNode* n = mScene->mRootNode->FindNode(b->mName); - if (!n) { - // this should never happen - std::stringstream err; - err << "Failed to find node for bone: \"" << name << "\""; - throw DeadlyExportError(err.str()); - } - node_by_bone[name] = n; - limbnodes.insert(n); - if (n == mScene->mRootNode) { continue; } + skeleton.insert(n); // mark all parent nodes as skeleton as well, // up until we find the root node, // or else the node containing the mesh, // or else the parent of a node containig the mesh. for ( const aiNode* parent = n->mParent; - parent != mScene->mRootNode; + parent && parent != mScene->mRootNode; parent = parent->mParent ) { + // if we've already done this node we can skip it all + if (skeleton.count(parent)) { + break; + } + // ignore fbx transform nodes as these will be collapsed later + // TODO: cache this by aiNode* + const std::string node_name(parent->mName.C_Str()); + if (node_name.find(MAGIC_NODE_TAG) != std::string::npos) { + continue; + } + // otherwise check if this is the root of the skeleton bool end = false; + // is the mesh part of this node? for (size_t i = 0; i < parent->mNumMeshes; ++i) { if (parent->mMeshes[i] == mi) { end = true; break; } } + // is the mesh in one of the children of this node? for (size_t j = 0; j < parent->mNumChildren; ++j) { aiNode* child = parent->mChildren[j]; for (size_t i = 0; i < child->mNumMeshes; ++i) { @@ -1513,27 +1534,23 @@ void FBXExporter::WriteObjects () } if (end) { break; } } - if (end) { break; } limbnodes.insert(parent); + skeleton.insert(parent); + // if it was the skeleton root we can finish here + if (end) { break; } } } + skeleton_by_mesh[mi] = skeleton; } // we'll need the uids for the bone nodes, so generate them now - std::map bone_uids; - for (auto &bone : limbnodes) { - std::string bone_name(bone->mName.C_Str()); - aiNode* bone_node = mScene->mRootNode->FindNode(bone->mName); - if (!bone_node) { - throw DeadlyExportError("Couldn't find node for bone" + bone_name); - } - auto elem = node_uids.find(bone_node); - if (elem == node_uids.end()) { - int64_t uid = generate_uid(); - node_uids[bone_node] = uid; - bone_uids[bone_name] = uid; - } else { - bone_uids[bone_name] = elem->second; + for (size_t i = 0; i < mScene->mNumMeshes; ++i) { + auto &s = skeleton_by_mesh[i]; + for (const aiNode* n : s) { + auto elem = node_uids.find(n); + if (elem == node_uids.end()) { + node_uids[n] = generate_uid(); + } } } @@ -1585,6 +1602,9 @@ void FBXExporter::WriteObjects () } } + // TODO, FIXME: this won't work if anything is not in the bind pose. + // for now if such a situation is detected, we throw an exception. + // first get this mesh's position in world space, // as we'll need it for each subdeformer. // @@ -1597,12 +1617,23 @@ void FBXExporter::WriteObjects () // but there's no guarantee that the bone is in the bindpose, // so this would be even less reliable. aiNode* mesh_node = get_node_for_mesh(mi, mScene->mRootNode); - aiMatrix4x4 mesh_node_xform = get_world_transform(mesh_node, mScene); + aiMatrix4x4 mesh_xform = get_world_transform(mesh_node, mScene); - // now make a subdeformer for each bone - for (size_t bi =0; bi < m->mNumBones; ++bi) { - const aiBone* b = m->mBones[bi]; - const std::string name(b->mName.C_Str()); + // now make a subdeformer for each bone in the skeleton + const std::set &skeleton = skeleton_by_mesh[mi]; + for (const aiNode* bone_node : skeleton) { + // if there's a bone for this node, find it + const aiBone* b = nullptr; + for (size_t bi = 0; bi < m->mNumBones; ++bi) { + // TODO: this probably should index by something else + const std::string name(m->mBones[bi]->mName.C_Str()); + if (node_by_bone[name] == bone_node) { + b = m->mBones[bi]; + break; + } + } + + // start the subdeformer node const int64_t subdeformer_uid = generate_uid(); FBX::Node sdnode("Deformer"); sdnode.AddProperties( @@ -1611,43 +1642,57 @@ void FBXExporter::WriteObjects () sdnode.AddChild("Version", int32_t(100)); sdnode.AddChild("UserData", "", ""); - // get indices and weights - std::vector subdef_indices; - std::vector subdef_weights; - int32_t last_index = -1; - for (size_t wi = 0; wi < b->mNumWeights; ++wi) { - int32_t vi = vertex_indices[b->mWeights[wi].mVertexId]; - if (vi == last_index) { - // only for vertices we exported to fbx - // TODO, FIXME: this assumes identically-located vertices - // will always deform in the same way. - // as assimp doesn't store a separate list of "positions", - // there's not much that can be done about this - // other than assuming that identical position means - // identical vertex. - continue; + // add indices and weights, if any + if (b) { + std::vector subdef_indices; + std::vector subdef_weights; + int32_t last_index = -1; + for (size_t wi = 0; wi < b->mNumWeights; ++wi) { + int32_t vi = vertex_indices[b->mWeights[wi].mVertexId]; + if (vi == last_index) { + // only for vertices we exported to fbx + // TODO, FIXME: this assumes identically-located vertices + // will always deform in the same way. + // as assimp doesn't store a separate list of "positions", + // there's not much that can be done about this + // other than assuming that identical position means + // identical vertex. + continue; + } + subdef_indices.push_back(vi); + subdef_weights.push_back(b->mWeights[wi].mWeight); + last_index = vi; } - subdef_indices.push_back(vi); - subdef_weights.push_back(b->mWeights[wi].mWeight); - last_index = vi; + // yes, "indexes" + sdnode.AddChild("Indexes", subdef_indices); + sdnode.AddChild("Weights", subdef_weights); } - // yes, "indexes" - sdnode.AddChild("Indexes", subdef_indices); - sdnode.AddChild("Weights", subdef_weights); - // transform is the transform of the mesh, but in bone space... - // which is exactly what assimp's mOffsetMatrix is, - // no matter what the assimp docs may say. - aiMatrix4x4 tr = b->mOffsetMatrix; + + // transform is the transform of the mesh, but in bone space. + // To get it we take the inverse of the world-space bone transform, + // and multiply by the world-space transform of the mesh. + aiMatrix4x4 bone_xform = get_world_transform(bone_node, mScene); + aiMatrix4x4 inverse_bone_xform = bone_xform; + inverse_bone_xform.Inverse(); + aiMatrix4x4 tr = inverse_bone_xform * mesh_xform; sdnode.AddChild("Transform", tr); + + // this should match assimp's mOffsetMatrix. + // if it doesn't then we have a problem. + // as assimp doesn't store a mOffsetMatrix for bones with 0 weight + // we have no way of reconstructing that information. + const float epsilon = 1e-5; // some error is to be expected + if (b && ! tr.Equal(b->mOffsetMatrix, epsilon)) { + std::stringstream err; + err << "transform matrix for bone \"" << b->mName.C_Str(); + err << "\" does not match mOffsetMatrix!"; + err << " Bones *must* be in the bind pose to export."; + throw DeadlyExportError(err.str()); + } + // transformlink should be the position of the bone in world space, - // in the bind pose. - // For now let's use the inverse of mOffsetMatrix, - // and the (assumedly static) mesh position in world space. - // TODO: find a better way of doing this? there aren't many options - tr = b->mOffsetMatrix; - tr.Inverse(); - tr *= mesh_node_xform; - sdnode.AddChild("TransformLink", tr); + // which we just calculated. + sdnode.AddChild("TransformLink", bone_xform); // done sdnode.Dump(outstream); @@ -1659,7 +1704,7 @@ void FBXExporter::WriteObjects () // we also need to connect the limb node to the subdeformer. c = FBX::Node("C"); - c.AddProperties("OO", bone_uids[name], subdeformer_uid); + c.AddProperties("OO", node_uids[bone_node], subdeformer_uid); connections.push_back(c); // TODO: emplace_back } @@ -1753,7 +1798,7 @@ void FBXExporter::WriteObjects () // write nodes (i.e. model heirarchy) // start at root node WriteModelNodes( - outstream, mScene->mRootNode, 0, bone_uids + outstream, mScene->mRootNode, 0, limbnodes ); object_node.End(outstream, true); @@ -1864,17 +1909,17 @@ void FBXExporter::WriteModelNodes( StreamWriterLE& s, const aiNode* node, int64_t parent_uid, - const std::map& bone_uids + const std::unordered_set& limbnodes ) { std::vector> chain; - WriteModelNodes(s, node, parent_uid, bone_uids, chain); + WriteModelNodes(s, node, parent_uid, limbnodes, chain); } void FBXExporter::WriteModelNodes( StreamWriterLE& outstream, const aiNode* node, int64_t parent_uid, - const std::map& bone_uids, + const std::unordered_set& limbnodes, std::vector>& transform_chain ) { // first collapse any expanded transformation chains created by FBX import. @@ -1924,7 +1969,7 @@ void FBXExporter::WriteModelNodes( } // now just continue to the next node WriteModelNodes( - outstream, next_node, parent_uid, bone_uids, transform_chain + outstream, next_node, parent_uid, limbnodes, transform_chain ); return; } @@ -1962,7 +2007,7 @@ void FBXExporter::WriteModelNodes( connections.push_back(c); // write model node WriteModelNode(outstream, node, node_uid, "Mesh", transform_chain); - } else if (bone_uids.count(node_name)) { + } else if (limbnodes.count(node)) { WriteModelNode(outstream, node, node_uid, "LimbNode", transform_chain); // we also need to write a nodeattribute to mark it as a skeleton int64_t node_attribute_uid = generate_uid(); @@ -2021,7 +2066,7 @@ void FBXExporter::WriteModelNodes( // now recurse into children for (size_t i = 0; i < node->mNumChildren; ++i) { WriteModelNodes( - outstream, node->mChildren[i], node_uid, bone_uids + outstream, node->mChildren[i], node_uid, limbnodes ); } } diff --git a/code/FBXExporter.h b/code/FBXExporter.h index 39c04ffee..ce2f67e24 100644 --- a/code/FBXExporter.h +++ b/code/FBXExporter.h @@ -56,6 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include #include // shared_ptr #include // stringstream @@ -129,13 +130,13 @@ namespace Assimp Assimp::StreamWriterLE& s, const aiNode* node, int64_t parent_uid, - const std::map& bone_uids + const std::unordered_set& limbnodes ); void WriteModelNodes( // usually don't call this directly StreamWriterLE& s, const aiNode* node, int64_t parent_uid, - const std::map& bone_uids, + const std::unordered_set& limbnodes, std::vector>& transform_chain ); }; From ce7673979be55db31893d22f6b0b6ed93baf91fc Mon Sep 17 00:00:00 2001 From: Tommy Date: Sun, 25 Feb 2018 10:10:07 +0100 Subject: [PATCH 050/278] assimp_cmd export: print error message on failure. --- tools/assimp_cmd/Main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/assimp_cmd/Main.cpp b/tools/assimp_cmd/Main.cpp index 1b4e5db45..14d00e1e1 100644 --- a/tools/assimp_cmd/Main.cpp +++ b/tools/assimp_cmd/Main.cpp @@ -334,7 +334,8 @@ bool ExportModel(const aiScene* pOut, PrintHorBar(); } if (res != AI_SUCCESS) { - printf("ERROR: Failed to write file\n"); + printf("Failed to write file\n"); + printf("ERROR: %s\n", globalExporter->GetErrorString()); return false; } From 9d9acf6840551d11423e32cd826d17b7da105d0f Mon Sep 17 00:00:00 2001 From: Tommy Date: Sun, 25 Feb 2018 11:45:38 +0100 Subject: [PATCH 051/278] FBX Export: allow export even when not in bind pose, iff all bones have an offset matrix defined. --- code/FBXExporter.cpp | 82 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 64 insertions(+), 18 deletions(-) diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index 6273f1977..f1c6290e2 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -1604,6 +1604,8 @@ void FBXExporter::WriteObjects () // TODO, FIXME: this won't work if anything is not in the bind pose. // for now if such a situation is detected, we throw an exception. + std::set not_in_bind_pose; + std::set no_offset_matrix; // first get this mesh's position in world space, // as we'll need it for each subdeformer. @@ -1612,10 +1614,6 @@ void FBXExporter::WriteObjects () // as it can be instanced to many nodes. // All we can do is assume no instancing, // and take the first node we find that contains the mesh. - // - // We could in stead take the transform from the bone's node, - // but there's no guarantee that the bone is in the bindpose, - // so this would be even less reliable. aiNode* mesh_node = get_node_for_mesh(mi, mScene->mRootNode); aiMatrix4x4 mesh_xform = get_world_transform(mesh_node, mScene); @@ -1632,6 +1630,9 @@ void FBXExporter::WriteObjects () break; } } + if (!b) { + no_offset_matrix.insert(bone_node); + } // start the subdeformer node const int64_t subdeformer_uid = generate_uid(); @@ -1669,30 +1670,52 @@ void FBXExporter::WriteObjects () } // transform is the transform of the mesh, but in bone space. - // To get it we take the inverse of the world-space bone transform, + // if the skeleton is in the bind pose, + // we can take the inverse of the world-space bone transform // and multiply by the world-space transform of the mesh. aiMatrix4x4 bone_xform = get_world_transform(bone_node, mScene); aiMatrix4x4 inverse_bone_xform = bone_xform; inverse_bone_xform.Inverse(); aiMatrix4x4 tr = inverse_bone_xform * mesh_xform; - sdnode.AddChild("Transform", tr); - // this should match assimp's mOffsetMatrix. - // if it doesn't then we have a problem. - // as assimp doesn't store a mOffsetMatrix for bones with 0 weight - // we have no way of reconstructing that information. + // this should be the same as the bone's mOffsetMatrix. + // if it's not the same, the skeleton isn't in the bind pose. const float epsilon = 1e-5; // some error is to be expected + bool bone_xform_okay = true; if (b && ! tr.Equal(b->mOffsetMatrix, epsilon)) { - std::stringstream err; - err << "transform matrix for bone \"" << b->mName.C_Str(); - err << "\" does not match mOffsetMatrix!"; - err << " Bones *must* be in the bind pose to export."; - throw DeadlyExportError(err.str()); + not_in_bind_pose.insert(b); + bone_xform_okay = false; } - // transformlink should be the position of the bone in world space, - // which we just calculated. - sdnode.AddChild("TransformLink", bone_xform); + // if we have a bone we should use the mOffsetMatrix, + // otherwise try to just use the calculated transform. + if (b) { + sdnode.AddChild("Transform", b->mOffsetMatrix); + } else { + sdnode.AddChild("Transform", tr); + } + // note: it doesn't matter if we mix these, + // because if they disagree we'll throw an exception later. + // it could be that the skeleton is not in the bone pose + // but all bones are still defined, + // in which case this would use the mOffsetMatrix for everything + // and a correct skeleton would still be output. + + // transformlink should be the position of the bone in world space. + // if the bone is in the bind pose (or nonexistant), + // we can just use the matrix we already calculated + if (bone_xform_okay) { + sdnode.AddChild("TransformLink", bone_xform); + // otherwise we can only work it out using the mesh position. + } else { + aiMatrix4x4 trl = b->mOffsetMatrix; + trl.Inverse(); + trl *= mesh_xform; + sdnode.AddChild("TransformLink", trl); + } + // note: this means we ALWAYS rely on the mesh node transform + // being unchanged from the time the skeleton was bound. + // there's not really any way around this at the moment. // done sdnode.Dump(outstream); @@ -1708,6 +1731,29 @@ void FBXExporter::WriteObjects () connections.push_back(c); // TODO: emplace_back } + // if we cannot create a valid FBX file, simply die. + // this will both prevent unnecessary bug reports, + // and tell the user what they can do to fix the situation + // (i.e. export their model in the bind pose). + if (no_offset_matrix.size() && not_in_bind_pose.size()) { + std::stringstream err; + err << "Not enough information to construct bind pose"; + err << " for mesh " << mi << "!"; + err << " Transform matrix for bone \""; + err << (*not_in_bind_pose.begin())->mName.C_Str() << "\""; + if (not_in_bind_pose.size() > 1) { + err << " (and " << not_in_bind_pose.size() - 1 << " more)"; + } + err << " does not match mOffsetMatrix,"; + err << " and node \""; + err << (*no_offset_matrix.begin())->mName.C_Str() << "\""; + if (no_offset_matrix.size() > 1) { + err << " (and " << no_offset_matrix.size() - 1 << " more)"; + } + err << " has no offset matrix to rely on."; + err << " Please ensure bones are in the bind pose to export."; + throw DeadlyExportError(err.str()); + } } From e99dfdb050c67844115e3849b4e39927aa2cdbd8 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 25 Feb 2018 21:03:09 +0100 Subject: [PATCH 052/278] fix cppcheck findings. --- code/3DSExporter.cpp | 2 +- code/3DSExporter.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/3DSExporter.cpp b/code/3DSExporter.cpp index 65f4bf8d8..fcd24d8aa 100644 --- a/code/3DSExporter.cpp +++ b/code/3DSExporter.cpp @@ -184,7 +184,7 @@ void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScen } // end of namespace Assimp // ------------------------------------------------------------------------------------------------ -Discreet3DSExporter:: Discreet3DSExporter(std::shared_ptr outfile, const aiScene* scene) +Discreet3DSExporter:: Discreet3DSExporter(std::shared_ptr &outfile, const aiScene* scene) : scene(scene) , writer(outfile) { diff --git a/code/3DSExporter.h b/code/3DSExporter.h index 5e138e92d..5db58a4cb 100644 --- a/code/3DSExporter.h +++ b/code/3DSExporter.h @@ -67,7 +67,7 @@ namespace Assimp // ------------------------------------------------------------------------------------------------ class Discreet3DSExporter { public: - Discreet3DSExporter(std::shared_ptr outfile, const aiScene* pScene); + Discreet3DSExporter(std::shared_ptr &outfile, const aiScene* pScene); ~Discreet3DSExporter(); private: From c0f04bf9652d02d8764d2b8aa837cd1ba338c825 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 27 Feb 2018 18:30:36 +0100 Subject: [PATCH 053/278] IMporter: fix lookup for tokens during inmemory imports. --- code/BaseImporter.cpp | 12 ++++++++++-- code/Importer/IFC/IFCLoader.cpp | 3 ++- test/unit/utIFCImportExport.cpp | 20 ++++++++++++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/code/BaseImporter.cpp b/code/BaseImporter.cpp index 0892efd9f..e7736d8a4 100644 --- a/code/BaseImporter.cpp +++ b/code/BaseImporter.cpp @@ -178,9 +178,17 @@ void BaseImporter::GetExtensionList(std::set& extensions) } *cur2 = '\0'; + std::string token; for (unsigned int i = 0; i < numTokens;++i) { - ai_assert(NULL != tokens[i]); - const char* r = strstr(buffer,tokens[i]); + ai_assert( nullptr != tokens[i] ); + size_t len( strlen( tokens[ i ] ) ); + token.clear(); + const char *ptr( tokens[ i ] ); + for ( size_t tokIdx = 0; tokIdx < len; ++tokIdx ) { + token.push_back( tolower( *ptr ) ); + ++ptr; + } + const char* r = strstr( buffer, token.c_str() ); if( !r ) { continue; } diff --git a/code/Importer/IFC/IFCLoader.cpp b/code/Importer/IFC/IFCLoader.cpp index de7a37037..5acc89545 100644 --- a/code/Importer/IFC/IFCLoader.cpp +++ b/code/Importer/IFC/IFCLoader.cpp @@ -141,7 +141,8 @@ bool IFCImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool // it is only unambiguous as long as we don't support any further // file formats with STEP as their encoding. const char* tokens[] = {"ISO-10303-21"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); + const bool found( SearchFileHeaderForToken( pIOHandler, pFile, tokens, 1 ) ); + return found; } return false; } diff --git a/test/unit/utIFCImportExport.cpp b/test/unit/utIFCImportExport.cpp index fa27bb7a8..e13244e34 100644 --- a/test/unit/utIFCImportExport.cpp +++ b/test/unit/utIFCImportExport.cpp @@ -62,3 +62,23 @@ public: TEST_F( utIFCImportExport, importIFCFromFileTest ) { EXPECT_TRUE( importerTest() ); } + +TEST_F( utIFCImportExport, importComplextypeAsColor ) { + std::string asset = + "ISO-10303-21;\n" + "HEADER;\n" + "FILE_DESCRIPTION( ( 'ViewDefinition [CoordinationView, SpaceBoundary2ndLevelAddOnView]', 'Option [Filter: ]' ), '2;1' );\n" + "FILE_NAME( 'S:\\[IFC]\\[COMPLETE-BUILDINGS]\\FZK-MODELS\\FZK-Haus\\ArchiCAD-14\\AC14-FZK-Haus.ifc', '2010-10-07T13:40:52', ( 'Architect' ), ( 'Building Designer Office' ), 'PreProc - EDM 5.0', 'ArchiCAD 14.00 Release 1. Windows Build Number of the Ifc 2x3 interface: 3427', 'The authorising person' );\n" + "FILE_SCHEMA( ( 'IFC2X3' ) );\n" + "ENDSEC;\n" + "\n" + "DATA;\n" + "#1 = IFCORGANIZATION( 'GS', 'Graphisoft', 'Graphisoft', $, $ );\n" + "#2 = IFCPROPERTYSINGLEVALUE( 'Red', $, IFCINTEGER( 255 ), $ );\n" + "#3 = IFCPROPERTYSINGLEVALUE( 'Green', $, IFCINTEGER( 255 ), $ );\n" + "#4 = IFCPROPERTYSINGLEVALUE( 'Blue', $, IFCINTEGER( 255 ), $ );\n" + "#5 = IFCCOMPLEXPROPERTY( 'Color', $, 'Color', ( #19, #20, #21 ) );\n"; + Assimp::Importer importer; + const aiScene *scene = importer.ReadFileFromMemory( asset.c_str(), asset.size(), 0 ); + +} From d53f95801180cce74123f58c08fd839222d2f4ff Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 27 Feb 2018 18:56:07 +0100 Subject: [PATCH 054/278] unittest: fix compiler warning --- test/unit/utIFCImportExport.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/unit/utIFCImportExport.cpp b/test/unit/utIFCImportExport.cpp index e13244e34..01132435b 100644 --- a/test/unit/utIFCImportExport.cpp +++ b/test/unit/utIFCImportExport.cpp @@ -80,5 +80,6 @@ TEST_F( utIFCImportExport, importComplextypeAsColor ) { "#5 = IFCCOMPLEXPROPERTY( 'Color', $, 'Color', ( #19, #20, #21 ) );\n"; Assimp::Importer importer; const aiScene *scene = importer.ReadFileFromMemory( asset.c_str(), asset.size(), 0 ); + EXPECT_EQ( nullptr, scene ); } From 190190c1d75c32e0f2a758c9bbe37bd085a0d59e Mon Sep 17 00:00:00 2001 From: Josh Faust Date: Tue, 27 Feb 2018 14:58:04 -0800 Subject: [PATCH 055/278] Fix material index off-by-one error in some OBJ files (seen in a C4D export) --- code/ObjFileMtlImporter.cpp | 5 ++-- test/models/OBJ/cube_mtllib_after_g.mtl | 5 ++++ test/models/OBJ/cube_mtllib_after_g.obj | 32 +++++++++++++++++++++++++ test/unit/utObjImportExport.cpp | 13 ++++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 test/models/OBJ/cube_mtllib_after_g.mtl create mode 100644 test/models/OBJ/cube_mtllib_after_g.obj diff --git a/code/ObjFileMtlImporter.cpp b/code/ObjFileMtlImporter.cpp index 835f529cc..584b3115c 100644 --- a/code/ObjFileMtlImporter.cpp +++ b/code/ObjFileMtlImporter.cpp @@ -303,11 +303,12 @@ void ObjFileMtlImporter::createMaterial() // New Material created m_pModel->m_pCurrentMaterial = new ObjFile::Material(); m_pModel->m_pCurrentMaterial->MaterialName.Set( name ); + m_pModel->m_MaterialLib.push_back( name ); + m_pModel->m_MaterialMap[ name ] = m_pModel->m_pCurrentMaterial; + if (m_pModel->m_pCurrentMesh) { m_pModel->m_pCurrentMesh->m_uiMaterialIndex = static_cast(m_pModel->m_MaterialLib.size() - 1); } - m_pModel->m_MaterialLib.push_back( name ); - m_pModel->m_MaterialMap[ name ] = m_pModel->m_pCurrentMaterial; } else { // Use older material m_pModel->m_pCurrentMaterial = (*it).second; diff --git a/test/models/OBJ/cube_mtllib_after_g.mtl b/test/models/OBJ/cube_mtllib_after_g.mtl new file mode 100644 index 000000000..63dde71af --- /dev/null +++ b/test/models/OBJ/cube_mtllib_after_g.mtl @@ -0,0 +1,5 @@ +newmtl MyMaterial +Ka 1.000 1.000 1.000 +Kd 1.000 1.000 1.000 +Ns 200.000 +Ks 0.050 0.050 0.050 diff --git a/test/models/OBJ/cube_mtllib_after_g.obj b/test/models/OBJ/cube_mtllib_after_g.obj new file mode 100644 index 000000000..dfd5997e8 --- /dev/null +++ b/test/models/OBJ/cube_mtllib_after_g.obj @@ -0,0 +1,32 @@ +g Object +mtllib cube_mtllib_after_g.mat +usemtl MyMaterial + +v 0.0 0.0 0.0 +v 0.0 0.0 1.0 +v 0.0 1.0 0.0 +v 0.0 1.0 1.0 +v 1.0 0.0 0.0 +v 1.0 0.0 1.0 +v 1.0 1.0 0.0 +v 1.0 1.0 1.0 + +vn 0.0 0.0 1.0 +vn 0.0 0.0 -1.0 +vn 0.0 1.0 0.0 +vn 0.0 -1.0 0.0 +vn 1.0 0.0 0.0 +vn -1.0 0.0 0.0 + +f 1//2 7//2 5//2 +f 1//2 3//2 7//2 +f 1//6 4//6 3//6 +f 1//6 2//6 4//6 +f 3//3 8//3 7//3 +f 3//3 4//3 8//3 +f 5//5 7//5 8//5 +f 5//5 8//5 6//5 +f 1//4 5//4 6//4 +f 1//4 6//4 2//4 +f 2//1 6//1 8//1 +f 2//1 8//1 4//1 diff --git a/test/unit/utObjImportExport.cpp b/test/unit/utObjImportExport.cpp index 5a2e42350..10207a5bf 100644 --- a/test/unit/utObjImportExport.cpp +++ b/test/unit/utObjImportExport.cpp @@ -354,3 +354,16 @@ TEST_F(utObjImportExport, 0based_array_Test) { const aiScene *scene = myimporter.ReadFileFromMemory(ObjModel.c_str(), ObjModel.size(), 0); EXPECT_EQ(nullptr, scene); } + +TEST_F( utObjImportExport, mtllib_after_g ) { + ::Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/cube_mtllib_after_g.obj", aiProcess_ValidateDataStructure ); + ASSERT_NE( nullptr, scene ); + + EXPECT_EQ(scene->mNumMeshes, 1U); + const aiMesh *mesh = scene->mMeshes[0]; + const aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex]; + aiString name; + ASSERT_EQ(aiReturn_SUCCESS, mat->Get(AI_MATKEY_NAME, name)); + EXPECT_STREQ("MyMaterial", name.C_Str()); +} \ No newline at end of file From a58f8e1c1a4127df2051ad955f87e4bab64909bd Mon Sep 17 00:00:00 2001 From: Tommy Date: Wed, 28 Feb 2018 23:38:49 +0100 Subject: [PATCH 056/278] FBX Export: add missing 0 value to file footer. --- code/FBXExporter.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index f1c6290e2..8e32ed46c 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -247,6 +247,11 @@ void FBXExporter::WriteBinaryFooter() outfile->Write("\x00", 1, 1); } + // not sure what this is, but it seems to always be 0 in modern files + for (size_t i = 0; i < 4; ++i) { + outfile->Write("\x00", 1, 1); + } + // now the file version again { StreamWriterLE outstream(outfile); From 701f9ccfe9c6fce31a6b7d798b9fc75afcbd0f38 Mon Sep 17 00:00:00 2001 From: Tommy Date: Sat, 3 Mar 2018 19:53:49 +0100 Subject: [PATCH 057/278] FBX Export: minor tweak to footer. Should now be identical to those output by the FBX SDK. --- code/FBXExporter.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index 8e32ed46c..a2e6024ed 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -235,9 +235,6 @@ void FBXExporter::WriteBinaryFooter() outfile->Write(NULL_RECORD.c_str(), NULL_RECORD.size(), 1); outfile->Write(GENERIC_FOOTID.c_str(), GENERIC_FOOTID.size(), 1); - for (size_t i = 0; i < 4; ++i) { - outfile->Write("\x00", 1, 1); - } // here some padding is added for alignment to 16 bytes. // if already aligned, the full 16 bytes is added. From 065c264b34fc3151acfe215af5fece11d5010c67 Mon Sep 17 00:00:00 2001 From: Alexandre Avenel Date: Sun, 4 Mar 2018 12:52:38 +0100 Subject: [PATCH 058/278] Fix #1415 : float-color.ply is broken float-color.ply was broken because it doesn't have a newline at the end. I'm not sure if a file without newline should be considered valid ? Added more checks to float-color unit-test in order to fail as excepted. Fixed the shipped unit test. Add postprocess validation to PLY unit tests --- test/models/PLY/float-color.ply | 2 +- test/unit/utPLYImportExport.cpp | 22 ++++++++++++++++------ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/test/models/PLY/float-color.ply b/test/models/PLY/float-color.ply index 34353ad53..f419be34e 100644 --- a/test/models/PLY/float-color.ply +++ b/test/models/PLY/float-color.ply @@ -15,4 +15,4 @@ end_header 0.0 0.0 0.0 0 0 1 1 100.0 0.0 0.0 0 0 1 1 200.0 200.0 0.0 0 0 1 1 -3 0 1 2 \ No newline at end of file +3 0 1 2 diff --git a/test/unit/utPLYImportExport.cpp b/test/unit/utPLYImportExport.cpp index 633beda5f..900f494f8 100644 --- a/test/unit/utPLYImportExport.cpp +++ b/test/unit/utPLYImportExport.cpp @@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "AbstractImportExportBase.h" +#include using namespace ::Assimp; @@ -52,7 +53,7 @@ class utPLYImportExport : public AbstractImportExportBase { public: virtual bool importerTest() { Assimp::Importer importer; - const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", 0 ); + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", aiProcess_ValidateDataStructure); EXPECT_EQ( 1u, scene->mNumMeshes ); EXPECT_NE( nullptr, scene->mMeshes[0] ); EXPECT_EQ( 8u, scene->mMeshes[0]->mNumVertices ); @@ -65,7 +66,7 @@ public: virtual bool exporterTest() { Importer importer; Exporter exporter; - const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", 0); + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", aiProcess_ValidateDataStructure); EXPECT_NE(nullptr, scene); EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "ply", ASSIMP_TEST_MODELS_DIR "/PLY/cube_test.ply")); @@ -89,19 +90,28 @@ TEST_F(utPLYImportExport, exportTest_Success ) { //Test issue 1623, crash when loading two PLY files in a row TEST_F(utPLYImportExport, importerMultipleTest) { Assimp::Importer importer; - const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", 0); + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", aiProcess_ValidateDataStructure); EXPECT_NE(nullptr, scene); - scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", 0); + scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", aiProcess_ValidateDataStructure); EXPECT_NE(nullptr, scene); } TEST_F( utPLYImportExport, vertexColorTest ) { Assimp::Importer importer; - const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/PLY/float-color.ply", 0 ); + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/PLY/float-color.ply", aiProcess_ValidateDataStructure); EXPECT_NE( nullptr, scene ); + EXPECT_EQ(1u, scene->mMeshes[0]->mNumFaces); + EXPECT_EQ(aiPrimitiveType_TRIANGLE, scene->mMeshes[0]->mPrimitiveTypes); + EXPECT_EQ(true, scene->mMeshes[0]->HasVertexColors(0)); + + auto first_face = scene->mMeshes[0]->mFaces[0]; + EXPECT_EQ(3, first_face.mNumIndices); + EXPECT_EQ(0, first_face.mIndices[0]); + EXPECT_EQ(1, first_face.mIndices[1]); + EXPECT_EQ(2, first_face.mIndices[2]); } static const char *test_file = @@ -125,6 +135,6 @@ static const char *test_file = TEST_F( utPLYImportExport, parseErrorTest ) { Assimp::Importer importer; - const aiScene *scene = importer.ReadFileFromMemory( test_file, strlen( test_file ), 0 ); + const aiScene *scene = importer.ReadFileFromMemory( test_file, strlen( test_file ), aiProcess_ValidateDataStructure); EXPECT_NE( nullptr, scene ); } From cd5881c9c05941f915c551416c2ef4673fb34e49 Mon Sep 17 00:00:00 2001 From: Alexandre Avenel Date: Sun, 4 Mar 2018 13:07:40 +0100 Subject: [PATCH 059/278] Add unit-test for PLY with UV coordinates --- test/models/PLY/cube_uv.ply | 45 +++++++++++++++++++++++++++++++++ test/unit/utPLYImportExport.cpp | 12 +++++++++ 2 files changed, 57 insertions(+) create mode 100644 test/models/PLY/cube_uv.ply diff --git a/test/models/PLY/cube_uv.ply b/test/models/PLY/cube_uv.ply new file mode 100644 index 000000000..45ab0607a --- /dev/null +++ b/test/models/PLY/cube_uv.ply @@ -0,0 +1,45 @@ +ply +format ascii 1.0 +comment Created by Blender 2.77 (sub 0) - www.blender.org, source file: '' +element vertex 24 +property float x +property float y +property float z +property float nx +property float ny +property float nz +property float s +property float t +element face 6 +property list uchar uint vertex_indices +end_header +1.000000 1.000000 -1.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 +1.000000 -1.000000 -1.000000 0.000000 0.000000 -1.000000 1.000000 0.000000 +-1.000000 -1.000000 -1.000000 0.000000 0.000000 -1.000000 1.000000 1.000000 +-1.000000 1.000000 -1.000000 0.000000 0.000000 -1.000000 0.000000 1.000000 +1.000000 0.999999 1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 +-1.000000 1.000000 1.000000 0.000000 -0.000000 1.000000 1.000000 0.000000 +-1.000000 -1.000000 1.000000 0.000000 -0.000000 1.000000 1.000000 1.000000 +0.999999 -1.000001 1.000000 0.000000 -0.000000 1.000000 0.000000 1.000000 +1.000000 1.000000 -1.000000 1.000000 -0.000000 0.000000 0.000000 0.000000 +1.000000 0.999999 1.000000 1.000000 -0.000000 0.000000 1.000000 0.000000 +0.999999 -1.000001 1.000000 1.000000 -0.000000 0.000000 1.000000 1.000000 +1.000000 -1.000000 -1.000000 1.000000 -0.000000 0.000000 0.000000 1.000000 +1.000000 -1.000000 -1.000000 -0.000000 -1.000000 -0.000000 0.000000 0.000000 +0.999999 -1.000001 1.000000 -0.000000 -1.000000 -0.000000 1.000000 0.000000 +-1.000000 -1.000000 1.000000 -0.000000 -1.000000 -0.000000 1.000000 1.000000 +-1.000000 -1.000000 -1.000000 -0.000000 -1.000000 -0.000000 0.000000 1.000000 +-1.000000 -1.000000 -1.000000 -1.000000 0.000000 -0.000000 0.000000 0.000000 +-1.000000 -1.000000 1.000000 -1.000000 0.000000 -0.000000 1.000000 0.000000 +-1.000000 1.000000 1.000000 -1.000000 0.000000 -0.000000 1.000000 1.000000 +-1.000000 1.000000 -1.000000 -1.000000 0.000000 -0.000000 0.000000 1.000000 +1.000000 0.999999 1.000000 0.000000 1.000000 0.000000 0.000000 0.000000 +1.000000 1.000000 -1.000000 0.000000 1.000000 0.000000 1.000000 0.000000 +-1.000000 1.000000 -1.000000 0.000000 1.000000 0.000000 1.000000 1.000000 +-1.000000 1.000000 1.000000 0.000000 1.000000 0.000000 0.000000 1.000000 +4 0 1 2 3 +4 4 5 6 7 +4 8 9 10 11 +4 12 13 14 15 +4 16 17 18 19 +4 20 21 22 23 diff --git a/test/unit/utPLYImportExport.cpp b/test/unit/utPLYImportExport.cpp index 900f494f8..0bef096e7 100644 --- a/test/unit/utPLYImportExport.cpp +++ b/test/unit/utPLYImportExport.cpp @@ -99,6 +99,18 @@ TEST_F(utPLYImportExport, importerMultipleTest) { EXPECT_NE(nullptr, scene); } +TEST_F(utPLYImportExport, importPLYwithUV) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube_uv.ply", aiProcess_ValidateDataStructure); + + EXPECT_NE(nullptr, scene); + EXPECT_NE(nullptr, scene->mMeshes[0]); + //This test model is using n-gons, so 6 faces instead of 12 tris + EXPECT_EQ(6u, scene->mMeshes[0]->mNumFaces); + EXPECT_EQ(aiPrimitiveType_POLYGON, scene->mMeshes[0]->mPrimitiveTypes); + EXPECT_EQ(true, scene->mMeshes[0]->HasTextureCoords(0)); +} + TEST_F( utPLYImportExport, vertexColorTest ) { Assimp::Importer importer; const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/PLY/float-color.ply", aiProcess_ValidateDataStructure); From bd80e92f788215708b5a0b7f3600c6d69df5c1ce Mon Sep 17 00:00:00 2001 From: Alexandre Avenel Date: Sun, 4 Mar 2018 12:42:21 +0100 Subject: [PATCH 060/278] Add PLY loader unit test for binary files --- test/models/PLY/cube_binary.ply | Bin 0 -> 447 bytes test/unit/utPLYImportExport.cpp | 10 ++++++++++ 2 files changed, 10 insertions(+) create mode 100644 test/models/PLY/cube_binary.ply diff --git a/test/models/PLY/cube_binary.ply b/test/models/PLY/cube_binary.ply new file mode 100644 index 0000000000000000000000000000000000000000..14d29ebd86d5be53fedd1933abe9b1bf95671c59 GIT binary patch literal 447 zcmZvW!EVAZ5JUrMLGoAZ7gSA8+>qdakb34C8D|5Q949iSBAobic8tmMeshes[0]->HasTextureCoords(0)); } +TEST_F(utPLYImportExport, importBinaryPLY) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube_binary.ply", 0); + + EXPECT_NE(nullptr, scene); + EXPECT_NE(nullptr, scene->mMeshes[0]); + //This test model is double sided, so 12 faces instead of 6 + EXPECT_EQ(12u, scene->mMeshes[0]->mNumFaces); +} + TEST_F( utPLYImportExport, vertexColorTest ) { Assimp::Importer importer; const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/PLY/float-color.ply", aiProcess_ValidateDataStructure); From d2547e84f530fa5a243f95068a17f50178f3ad47 Mon Sep 17 00:00:00 2001 From: Alexandre Avenel Date: Sun, 4 Mar 2018 21:41:19 +0100 Subject: [PATCH 061/278] Fix for undefined behavior when loading binary PLY This commit fix undefined behavior reported by UBSAN when loading a binary PLY file. --- code/PlyParser.cpp | 68 ++++++++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/code/PlyParser.cpp b/code/PlyParser.cpp index 85c0f823e..672ac9bde 100644 --- a/code/PlyParser.cpp +++ b/code/PlyParser.cpp @@ -1043,71 +1043,91 @@ bool PLY::PropertyInstance::ParseValueBinary(IOStreamBuffer &streamBuffer, switch (eType) { case EDT_UInt: - out->iUInt = (uint32_t)*((uint32_t*)pCur); - pCur += 4; + { + uint32_t t; + memcpy(&t, pCur, sizeof(uint32_t)); + pCur += sizeof(uint32_t); // Swap endianness - if (p_bBE)ByteSwap::Swap((int32_t*)&out->iUInt); + if (p_bBE)ByteSwap::Swap(&t); + out->iUInt = t; break; + } case EDT_UShort: { - uint16_t i = *((uint16_t*)pCur); + uint16_t t; + memcpy(&t, pCur, sizeof(uint16_t)); + pCur += sizeof(uint16_t); // Swap endianness - if (p_bBE)ByteSwap::Swap(&i); - out->iUInt = (uint32_t)i; - pCur += 2; + if (p_bBE)ByteSwap::Swap(&t); + out->iUInt = t; break; } case EDT_UChar: { - out->iUInt = (uint32_t)(*((uint8_t*)pCur)); - pCur++; + uint8_t t; + memcpy(&t, pCur, sizeof(uint8_t)); + pCur += sizeof(uint8_t); + out->iUInt = t; break; } case EDT_Int: - out->iInt = *((int32_t*)pCur); - pCur += 4; + { + int32_t t; + memcpy(&t, pCur, sizeof(int32_t)); + pCur += sizeof(int32_t); // Swap endianness - if (p_bBE)ByteSwap::Swap(&out->iInt); + if (p_bBE)ByteSwap::Swap(&t); + out->iInt = t; break; + } case EDT_Short: { - int16_t i = *((int16_t*)pCur); + int16_t t; + memcpy(&t, pCur, sizeof(int16_t)); + pCur += sizeof(int16_t); // Swap endianness - if (p_bBE)ByteSwap::Swap(&i); - out->iInt = (int32_t)i; - pCur += 2; + if (p_bBE)ByteSwap::Swap(&t); + out->iInt = t; break; } case EDT_Char: - out->iInt = (int32_t)*((int8_t*)pCur); - pCur++; + { + int8_t t; + memcpy(&t, pCur, sizeof(int8_t)); + pCur += sizeof(int8_t); + out->iInt = t; break; + } case EDT_Float: { - out->fFloat = *((float*)pCur); + float t; + memcpy(&t, pCur, sizeof(float)); + pCur += sizeof(float); // Swap endianness - if (p_bBE)ByteSwap::Swap((int32_t*)&out->fFloat); - pCur += 4; + if (p_bBE)ByteSwap::Swap(&t); + out->fFloat = t; break; } case EDT_Double: { - out->fDouble = *((double*)pCur); + double t; + memcpy(&t, pCur, sizeof(double)); + pCur += sizeof(double); // Swap endianness - if (p_bBE)ByteSwap::Swap((int64_t*)&out->fDouble); - pCur += 8; + if (p_bBE)ByteSwap::Swap(&t); + out->fDouble = t; break; } default: From ecb64c5949b534a416726ed5f8e2fbfdc8962ebd Mon Sep 17 00:00:00 2001 From: Alexandre Avenel Date: Sat, 3 Mar 2018 16:44:15 +0100 Subject: [PATCH 062/278] Add unit test for issue 623 --- test/models/PLY/issue623.ply | 36 +++++++++++++++++++++++++++++++++ test/unit/utPLYImportExport.cpp | 12 +++++++++++ 2 files changed, 48 insertions(+) create mode 100644 test/models/PLY/issue623.ply diff --git a/test/models/PLY/issue623.ply b/test/models/PLY/issue623.ply new file mode 100644 index 000000000..af8811752 --- /dev/null +++ b/test/models/PLY/issue623.ply @@ -0,0 +1,36 @@ +ply +format ascii 1.0 +comment Created by Blender 2.77 (sub 0) - www.blender.org, source file: '' +element vertex 24 +property float x +property float y +property float z +property float nx +property float ny +property float nz +property list uchar uint vertex_indices +end_header +7.941797 1.432409 -0.927566 0.000000 0.000000 -1.000000 +7.941797 -2.321273 -0.927566 0.000000 0.000000 -1.000000 +4.188114 -2.321273 -0.927566 0.000000 0.000000 -1.000000 +4.188115 1.432410 -0.927566 0.000000 0.000000 -1.000000 +7.941798 1.432408 2.826117 0.000000 -0.000000 1.000000 +4.188114 1.432409 2.826117 0.000000 -0.000000 1.000000 +4.188113 -2.321273 2.826117 0.000000 -0.000000 1.000000 +7.941795 -2.321275 2.826117 0.000000 -0.000000 1.000000 +7.941797 1.432409 -0.927566 1.000000 -0.000000 0.000000 +7.941798 1.432408 2.826117 1.000000 -0.000000 0.000000 +7.941795 -2.321275 2.826117 1.000000 -0.000000 0.000000 +7.941797 -2.321273 -0.927566 1.000000 -0.000000 0.000000 +7.941797 -2.321273 -0.927566 -0.000000 -1.000000 -0.000000 +7.941795 -2.321275 2.826117 -0.000000 -1.000000 -0.000000 +4.188113 -2.321273 2.826117 -0.000000 -1.000000 -0.000000 +4.188114 -2.321273 -0.927566 -0.000000 -1.000000 -0.000000 +4.188114 -2.321273 -0.927566 -1.000000 0.000000 -0.000000 +4.188113 -2.321273 2.826117 -1.000000 0.000000 -0.000000 +4.188114 1.432409 2.826117 -1.000000 0.000000 -0.000000 +4.188115 1.432410 -0.927566 -1.000000 0.000000 -0.000000 +7.941798 1.432408 2.826117 0.000000 1.000000 0.000000 +7.941797 1.432409 -0.927566 0.000000 1.000000 0.000000 +4.188115 1.432410 -0.927566 0.000000 1.000000 0.000000 +4.188114 1.432409 2.826117 0.000000 1.000000 0.000000 diff --git a/test/unit/utPLYImportExport.cpp b/test/unit/utPLYImportExport.cpp index e5268a400..4e4b4dce9 100644 --- a/test/unit/utPLYImportExport.cpp +++ b/test/unit/utPLYImportExport.cpp @@ -136,6 +136,18 @@ TEST_F( utPLYImportExport, vertexColorTest ) { EXPECT_EQ(2, first_face.mIndices[2]); } +//Test issue #623, PLY importer should not automatically create faces +TEST_F(utPLYImportExport, pointcloudTest) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/issue623.ply", 0); + EXPECT_NE(nullptr, scene); + + EXPECT_EQ(1u, scene->mNumMeshes); + EXPECT_NE(nullptr, scene->mMeshes[0]); + EXPECT_EQ(24u, scene->mMeshes[0]->mNumVertices); + EXPECT_EQ(0u, scene->mMeshes[0]->mNumFaces); +} + static const char *test_file = "ply\n" "format ascii 1.0\n" From f053695176517da997fdb549f65bcc741112d786 Mon Sep 17 00:00:00 2001 From: Alexandre Avenel Date: Sat, 3 Mar 2018 16:56:48 +0100 Subject: [PATCH 063/278] Fix issue #623 PLY importer should not create faces When the PLY file contains no faces, we should not create them. --- code/PlyLoader.cpp | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/code/PlyLoader.cpp b/code/PlyLoader.cpp index 5f4e556c1..88be670cc 100644 --- a/code/PlyLoader.cpp +++ b/code/PlyLoader.cpp @@ -244,30 +244,6 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy // if no face list is existing we assume that the vertex // list is containing a list of points bool pointsOnly = mGeneratedMesh->mFaces == NULL ? true : false; - if (pointsOnly) { - if (mGeneratedMesh->mNumVertices < 3) { - if (mGeneratedMesh != NULL) { - delete(mGeneratedMesh); - mGeneratedMesh = nullptr; - } - - streamedBuffer.close(); - throw DeadlyImportError("Invalid .ply file: Not enough " - "vertices to build a proper face list. "); - } - - const unsigned int iNum = (unsigned int)mGeneratedMesh->mNumVertices / 3; - mGeneratedMesh->mNumFaces = iNum; - mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces]; - - for (unsigned int i = 0; i < iNum; ++i) { - mGeneratedMesh->mFaces[i].mNumIndices = 3; - mGeneratedMesh->mFaces[i].mIndices = new unsigned int[3]; - mGeneratedMesh->mFaces[i].mIndices[0] = (i * 3); - mGeneratedMesh->mFaces[i].mIndices[1] = (i * 3) + 1; - mGeneratedMesh->mFaces[i].mIndices[2] = (i * 3) + 2; - } - } // now load a list of all materials std::vector avMaterials; From 15fa86f100e1d4e4b71593198c408132fc827a97 Mon Sep 17 00:00:00 2001 From: Alexandre Avenel Date: Sun, 4 Mar 2018 00:12:53 +0100 Subject: [PATCH 064/278] Set primitive_type to point when PLY is a point cloud --- code/PlyLoader.cpp | 3 +++ test/unit/utPLYImportExport.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/code/PlyLoader.cpp b/code/PlyLoader.cpp index 88be670cc..1bdd6e694 100644 --- a/code/PlyLoader.cpp +++ b/code/PlyLoader.cpp @@ -244,6 +244,9 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy // if no face list is existing we assume that the vertex // list is containing a list of points bool pointsOnly = mGeneratedMesh->mFaces == NULL ? true : false; + if (pointsOnly) { + mGeneratedMesh->mPrimitiveTypes = aiPrimitiveType::aiPrimitiveType_POINT; + } // now load a list of all materials std::vector avMaterials; diff --git a/test/unit/utPLYImportExport.cpp b/test/unit/utPLYImportExport.cpp index 4e4b4dce9..c19571199 100644 --- a/test/unit/utPLYImportExport.cpp +++ b/test/unit/utPLYImportExport.cpp @@ -97,6 +97,8 @@ TEST_F(utPLYImportExport, importerMultipleTest) { scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", aiProcess_ValidateDataStructure); EXPECT_NE(nullptr, scene); + EXPECT_NE(nullptr, scene->mMeshes[0]); + EXPECT_EQ(6u, scene->mMeshes[0]->mNumFaces); } TEST_F(utPLYImportExport, importPLYwithUV) { @@ -145,6 +147,7 @@ TEST_F(utPLYImportExport, pointcloudTest) { EXPECT_EQ(1u, scene->mNumMeshes); EXPECT_NE(nullptr, scene->mMeshes[0]); EXPECT_EQ(24u, scene->mMeshes[0]->mNumVertices); + EXPECT_EQ(aiPrimitiveType::aiPrimitiveType_POINT, scene->mMeshes[0]->mPrimitiveTypes); EXPECT_EQ(0u, scene->mMeshes[0]->mNumFaces); } From e7869c7db3392217e0e2cf9056798bc8f4f00e47 Mon Sep 17 00:00:00 2001 From: Alexandre Avenel Date: Sun, 4 Mar 2018 23:10:30 +0100 Subject: [PATCH 065/278] PLY unit test : Fix aiPostProcess validation errors --- test/unit/utPLYImportExport.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/unit/utPLYImportExport.cpp b/test/unit/utPLYImportExport.cpp index c19571199..e0f96195b 100644 --- a/test/unit/utPLYImportExport.cpp +++ b/test/unit/utPLYImportExport.cpp @@ -115,7 +115,7 @@ TEST_F(utPLYImportExport, importPLYwithUV) { TEST_F(utPLYImportExport, importBinaryPLY) { Assimp::Importer importer; - const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube_binary.ply", 0); + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube_binary.ply", aiProcess_ValidateDataStructure); EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene->mMeshes[0]); @@ -141,6 +141,7 @@ TEST_F( utPLYImportExport, vertexColorTest ) { //Test issue #623, PLY importer should not automatically create faces TEST_F(utPLYImportExport, pointcloudTest) { Assimp::Importer importer; + //Could not use aiProcess_ValidateDataStructure since it's missing faces. const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/issue623.ply", 0); EXPECT_NE(nullptr, scene); @@ -172,6 +173,7 @@ static const char *test_file = TEST_F( utPLYImportExport, parseErrorTest ) { Assimp::Importer importer; - const aiScene *scene = importer.ReadFileFromMemory( test_file, strlen( test_file ), aiProcess_ValidateDataStructure); + //Could not use aiProcess_ValidateDataStructure since it's missing faces. + const aiScene *scene = importer.ReadFileFromMemory( test_file, strlen( test_file ), 0); EXPECT_NE( nullptr, scene ); } From d82fff757bcb003cb10af9d11f862b8451bebbde Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 5 Mar 2018 15:01:37 +0100 Subject: [PATCH 066/278] Update utObjImportExport.cpp Add missing end of line. --- test/unit/utObjImportExport.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/utObjImportExport.cpp b/test/unit/utObjImportExport.cpp index 10207a5bf..8aec9c443 100644 --- a/test/unit/utObjImportExport.cpp +++ b/test/unit/utObjImportExport.cpp @@ -366,4 +366,4 @@ TEST_F( utObjImportExport, mtllib_after_g ) { aiString name; ASSERT_EQ(aiReturn_SUCCESS, mat->Get(AI_MATKEY_NAME, name)); EXPECT_STREQ("MyMaterial", name.C_Str()); -} \ No newline at end of file +} From f4c37fa2455f9928348165213fe2a00892fef753 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Sat, 3 Mar 2018 17:03:30 +0100 Subject: [PATCH 067/278] Collada: add importer property that forces the use of collada names. Closes #1375. --- code/ColladaLoader.cpp | 6 ++++++ code/ColladaLoader.h | 1 + include/assimp/config.h.in | 10 ++++++++++ 3 files changed, 17 insertions(+) diff --git a/code/ColladaLoader.cpp b/code/ColladaLoader.cpp index a3516f9c4..959a905ae 100644 --- a/code/ColladaLoader.cpp +++ b/code/ColladaLoader.cpp @@ -131,6 +131,7 @@ void ColladaLoader::SetupProperties(const Importer* pImp) { noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0; ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION,0) != 0; + useColladaName = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES,0) != 0; } // ------------------------------------------------------------------------------------------------ @@ -1913,6 +1914,11 @@ const Collada::Node* ColladaLoader::FindNodeBySID( const Collada::Node* pNode, c // The name must be unique for proper node-bone association. std::string ColladaLoader::FindNameForNode( const Collada::Node* pNode) { + // If explicitly requested, just use the collada name. + if (useColladaName) { + return pNode->mName; + } + // Now setup the name of the assimp node. The collada name might not be // unique, so we use the collada ID. if (!pNode->mID.empty()) diff --git a/code/ColladaLoader.h b/code/ColladaLoader.h index c63bf2945..d61845b24 100644 --- a/code/ColladaLoader.h +++ b/code/ColladaLoader.h @@ -248,6 +248,7 @@ protected: bool noSkeletonMesh; bool ignoreUpDirection; + bool useColladaName; /** Used by FindNameForNode() to generate unique node names */ unsigned int mNodeNameCounter; diff --git a/include/assimp/config.h.in b/include/assimp/config.h.in index 071d58cd2..c9555fb38 100644 --- a/include/assimp/config.h.in +++ b/include/assimp/config.h.in @@ -934,6 +934,16 @@ enum aiComponent */ #define AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION "IMPORT_COLLADA_IGNORE_UP_DIRECTION" +// --------------------------------------------------------------------------- +/** @brief Specifies whether the Collada loader should use Collada names as node names. + * + * If this property is set to true, the Collada names will be used as the + * node name. The default is to use the id tag (resp. sid tag, if no id tag is present) + * instead. + * Property type: Bool. Default value: false. + */ +#define AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES "IMPORT_COLLADA_USE_COLLADA_NAMES" + // ---------- All the Export defines ------------ /** @brief Specifies the xfile use double for real values of float From 05cf8bfb2ef1289b81a06907d540e78d74c5ee48 Mon Sep 17 00:00:00 2001 From: JeffH-BMG <37119778+JeffH-BMG@users.noreply.github.com> Date: Tue, 6 Mar 2018 13:48:11 -0500 Subject: [PATCH 068/278] Fix import of binary STL files in double-precision builds When ASSIMP_DOUBLE_PRECISION is used, the STL loader attempts to read 8-byte double vertex and normal values from the STL file. STL files are written using 4-byte floats, however, and the import will read past the end of the buffer, and possibly crash. --- code/STLLoader.cpp | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/code/STLLoader.cpp b/code/STLLoader.cpp index fc326b2c7..863f7affd 100644 --- a/code/STLLoader.cpp +++ b/code/STLLoader.cpp @@ -449,26 +449,29 @@ bool STLImporter::LoadBinaryFile() aiVector3D *vp = pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; aiVector3D *vn = pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; + typedef aiVector3t aiVector3F; + aiVector3F* theVec; + for ( unsigned int i = 0; i < pMesh->mNumFaces; ++i ) { // NOTE: Blender sometimes writes empty normals ... this is not // our fault ... the RemoveInvalidData helper step should fix that - ::memcpy( vn, sz, sizeof( aiVector3D ) ); - sz += sizeof(aiVector3D); - *(vn+1) = *vn; - *(vn+2) = *vn; - vn += 3; - ::memcpy( vp, sz, sizeof( aiVector3D ) ); - ++vp; - sz += sizeof(aiVector3D); + // There's one normal for the face in the STL; use it three times + // for vertex normals + theVec = (aiVector3F*) sz; + *vn++ = *theVec; + *vn++ = *theVec; + *vn++ = *theVec++; - ::memcpy( vp, sz, sizeof( aiVector3D ) ); - ++vp; - sz += sizeof(aiVector3D); + // vertex 1 + *vp++ = *theVec++; - ::memcpy( vp, sz, sizeof( aiVector3D ) ); - ++vp; - sz += sizeof(aiVector3D); + // vertex 2 + *vp++ = *theVec++; + + // vertex 3 + *vp++ = *theVec; + sz += 4 * sizeof aiVector3F; uint16_t color = *((uint16_t*)sz); sz += 2; From 0dab5c508e15d72ac9502a7e9f155ab880fa58e2 Mon Sep 17 00:00:00 2001 From: JeffH-BMG <37119778+JeffH-BMG@users.noreply.github.com> Date: Tue, 6 Mar 2018 13:55:32 -0500 Subject: [PATCH 069/278] STL binary Export should write 4-byte floats for vertex and normal coordinates The STL binary format uses 4-byte floats. When using double-precision builds of Asset Importer, the STL exporter was writing out 8-byte double values instead.. --- code/STLExporter.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/code/STLExporter.cpp b/code/STLExporter.cpp index 4c7a8a639..3d681f8c7 100644 --- a/code/STLExporter.cpp +++ b/code/STLExporter.cpp @@ -172,12 +172,16 @@ void STLExporter :: WriteMeshBinary(const aiMesh* m) } nor.Normalize(); } - ai_real nx = nor.x, ny = nor.y, nz = nor.z; + // STL binary files use 4-byte floats. This may possibly cause loss of precision + // for clients using 8-byte doubles + float nx = (float) nor.x; + float ny = (float) nor.y; + float nz = (float) nor.z; AI_SWAP4(nx); AI_SWAP4(ny); AI_SWAP4(nz); mOutput.write((char *)&nx, 4); mOutput.write((char *)&ny, 4); mOutput.write((char *)&nz, 4); for(unsigned int a = 0; a < f.mNumIndices; ++a) { const aiVector3D& v = m->mVertices[f.mIndices[a]]; - ai_real vx = v.x, vy = v.y, vz = v.z; + float vx = (float) v.x, vy = (float) v.y, vz = (float) v.z; AI_SWAP4(vx); AI_SWAP4(vy); AI_SWAP4(vz); mOutput.write((char *)&vx, 4); mOutput.write((char *)&vy, 4); mOutput.write((char *)&vz, 4); } From 5ea06e1bb69e4b61c3f05160c9c38ed1187a5102 Mon Sep 17 00:00:00 2001 From: JeffH-BMG <37119778+JeffH-BMG@users.noreply.github.com> Date: Tue, 6 Mar 2018 14:50:02 -0500 Subject: [PATCH 070/278] Add support for texture file in PLY exports The PLY format has an unofficial way to specify an associated texture, using the "comment TextureFile" comment line. The PLY loader supports this, but the exporter does not. The change looks for a diffuse texture in the scene's materials, and if it finds one, it adds it to the exported mesh using "comment TextureFile". --- code/PlyExporter.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/code/PlyExporter.cpp b/code/PlyExporter.cpp index 0ddba0d2a..2d528c96c 100644 --- a/code/PlyExporter.cpp +++ b/code/PlyExporter.cpp @@ -148,6 +148,17 @@ PlyExporter::PlyExporter(const char* _filename, const aiScene* pScene, bool bina << aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.' << aiGetVersionRevision() << ")" << endl; + // Look through materials for a diffuse texture, and add it if found + for ( unsigned int i = 0; i < pScene->mNumMaterials; ++i ) + { + const aiMaterial* const mat = pScene->mMaterials[i]; + aiString s; + if ( AI_SUCCESS == mat->Get( AI_MATKEY_TEXTURE_DIFFUSE( 0 ), s ) ) + { + mOutput << "comment TextureFile " << s.data << endl; + } + } + // TODO: probably want to check here rather than just assume something // definitely not good to always write float even if we might have double precision From 6fd64b95c32699649e6e392fb05bbf0af01cd685 Mon Sep 17 00:00:00 2001 From: JeffH-BMG <37119778+JeffH-BMG@users.noreply.github.com> Date: Tue, 6 Mar 2018 15:03:44 -0500 Subject: [PATCH 071/278] Fix compile error Add parens to use of 'sizeof' operator --- code/STLLoader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/STLLoader.cpp b/code/STLLoader.cpp index 863f7affd..115e5f816 100644 --- a/code/STLLoader.cpp +++ b/code/STLLoader.cpp @@ -471,7 +471,7 @@ bool STLImporter::LoadBinaryFile() // vertex 3 *vp++ = *theVec; - sz += 4 * sizeof aiVector3F; + sz += 4 * sizeof( aiVector3F ); uint16_t color = *((uint16_t*)sz); sz += 2; From 9f02c8a97c530e4d5d3ccf70688fd0f84e9c1923 Mon Sep 17 00:00:00 2001 From: Tommy Date: Thu, 1 Mar 2018 18:03:04 +0100 Subject: [PATCH 072/278] Fix default opacity of materials exported to FBX by Blender. --- code/FBXMaterial.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/code/FBXMaterial.cpp b/code/FBXMaterial.cpp index 10f3bbe6c..8bb3920de 100644 --- a/code/FBXMaterial.cpp +++ b/code/FBXMaterial.cpp @@ -54,6 +54,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXProperties.h" #include +#include // std::transform + namespace Assimp { namespace FBX { @@ -82,11 +84,12 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con std::string templateName; - const char* const sh = shading.c_str(); - if(!strcmp(sh,"phong")) { + // lower-case shading because Blender (for example) writes "Phong" + std::transform(shading.begin(), shading.end(), shading.begin(), ::tolower); + if(shading == "phong") { templateName = "Material.FbxSurfacePhong"; } - else if(!strcmp(sh,"lambert")) { + else if(shading == "lambert") { templateName = "Material.FbxSurfaceLambert"; } else { From 89a4cf94957711117e7c64d483bb1fe42d05f7e9 Mon Sep 17 00:00:00 2001 From: JeffH-BMG <37119778+JeffH-BMG@users.noreply.github.com> Date: Wed, 7 Mar 2018 17:26:01 -0500 Subject: [PATCH 073/278] Respond to comments Use memcpy() to read normals and vertices, to mitigate alignment issues, per comments. --- code/STLLoader.cpp | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/code/STLLoader.cpp b/code/STLLoader.cpp index 115e5f816..e01162a30 100644 --- a/code/STLLoader.cpp +++ b/code/STLLoader.cpp @@ -451,6 +451,7 @@ bool STLImporter::LoadBinaryFile() typedef aiVector3t aiVector3F; aiVector3F* theVec; + aiVector3F theVec3F; for ( unsigned int i = 0; i < pMesh->mNumFaces; ++i ) { // NOTE: Blender sometimes writes empty normals ... this is not @@ -459,19 +460,32 @@ bool STLImporter::LoadBinaryFile() // There's one normal for the face in the STL; use it three times // for vertex normals theVec = (aiVector3F*) sz; - *vn++ = *theVec; - *vn++ = *theVec; - *vn++ = *theVec++; + ::memcpy( &theVec3F, theVec, sizeof(aiVector3F) ); + vn->x = theVec3F.x; vn->y = theVec3F.y; vn->z = theVec3F.z; + *(vn+1) = *vn; + *(vn+2) = *vn; + ++theVec; + vn += 3; // vertex 1 - *vp++ = *theVec++; + ::memcpy( &theVec3F, theVec, sizeof(aiVector3F) ); + vp->x = theVec3F.x; vp->y = theVec3F.y; vp->z = theVec3F.z; + ++theVec; + ++vp; // vertex 2 - *vp++ = *theVec++; + ::memcpy( &theVec3F, theVec, sizeof(aiVector3F) ); + vp->x = theVec3F.x; vp->y = theVec3F.y; vp->z = theVec3F.z; + ++theVec; + ++vp; // vertex 3 - *vp++ = *theVec; - sz += 4 * sizeof( aiVector3F ); + ::memcpy( &theVec3F, theVec, sizeof(aiVector3F) ); + vp->x = theVec3F.x; vp->y = theVec3F.y; vp->z = theVec3F.z; + ++theVec; + ++vp; + + sz = theVec; uint16_t color = *((uint16_t*)sz); sz += 2; From cfd56a43a578f77a1c63a95ed28084a3ae3c4e6e Mon Sep 17 00:00:00 2001 From: JeffH-BMG <37119778+JeffH-BMG@users.noreply.github.com> Date: Wed, 7 Mar 2018 18:24:38 -0500 Subject: [PATCH 074/278] Fix compile error Fixed bad cast. --- code/STLLoader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/STLLoader.cpp b/code/STLLoader.cpp index e01162a30..3a85a5495 100644 --- a/code/STLLoader.cpp +++ b/code/STLLoader.cpp @@ -485,7 +485,7 @@ bool STLImporter::LoadBinaryFile() ++theVec; ++vp; - sz = theVec; + sz = (const unsigned char*) theVec; uint16_t color = *((uint16_t*)sz); sz += 2; From 69742670dd55b256923bed0feb52d45146af97c8 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 9 Mar 2018 11:40:45 +0100 Subject: [PATCH 075/278] 3mf: use correct material assignment in case of multi-materials. --- code/3MFXmlTags.h | 1 + code/BaseImporter.cpp | 16 ++++----- code/D3MFExporter.cpp | 7 +++- code/D3MFExporter.h | 1 + code/D3MFImporter.cpp | 78 +++++++++++++++++++++++++++++++---------- code/D3MFOpcPackage.cpp | 59 ++++++++++++++++--------------- code/D3MFOpcPackage.h | 9 ++--- 7 files changed, 110 insertions(+), 61 deletions(-) diff --git a/code/3MFXmlTags.h b/code/3MFXmlTags.h index c4da2970d..feedf4538 100644 --- a/code/3MFXmlTags.h +++ b/code/3MFXmlTags.h @@ -74,6 +74,7 @@ namespace XmlTag { // Material definitions static const std::string basematerials = "basematerials"; + static const std::string basematerials_id = "id"; static const std::string basematerials_base = "base"; static const std::string basematerials_name = "name"; static const std::string basematerials_displaycolor = "displaycolor"; diff --git a/code/BaseImporter.cpp b/code/BaseImporter.cpp index e7736d8a4..67c743285 100644 --- a/code/BaseImporter.cpp +++ b/code/BaseImporter.cpp @@ -115,13 +115,12 @@ void BaseImporter::SetupProperties(const Importer* /*pImp*/) } // ------------------------------------------------------------------------------------------------ -void BaseImporter::GetExtensionList(std::set& extensions) -{ +void BaseImporter::GetExtensionList(std::set& extensions) { const aiImporterDesc* desc = GetInfo(); - ai_assert(desc != NULL); + ai_assert(desc != nullptr); const char* ext = desc->mFileExtensions; - ai_assert(ext != NULL); + ai_assert(ext != nullptr ); const char* last = ext; do { @@ -145,12 +144,13 @@ void BaseImporter::GetExtensionList(std::set& extensions) unsigned int searchBytes /* = 200 */, bool tokensSol /* false */) { - ai_assert( NULL != tokens ); + ai_assert( nullptr != tokens ); ai_assert( 0 != numTokens ); ai_assert( 0 != searchBytes); - if (!pIOHandler) + if ( nullptr == pIOHandler ) { return false; + } std::unique_ptr pStream (pIOHandler->Open(pFile)); if (pStream.get() ) { @@ -179,9 +179,9 @@ void BaseImporter::GetExtensionList(std::set& extensions) *cur2 = '\0'; std::string token; - for (unsigned int i = 0; i < numTokens;++i) { + for (unsigned int i = 0; i < numTokens; ++i ) { ai_assert( nullptr != tokens[i] ); - size_t len( strlen( tokens[ i ] ) ); + const size_t len( strlen( tokens[ i ] ) ); token.clear(); const char *ptr( tokens[ i ] ); for ( size_t tokIdx = 0; tokIdx < len; ++tokIdx ) { diff --git a/code/D3MFExporter.cpp b/code/D3MFExporter.cpp index 91f06fc87..a74280af7 100644 --- a/code/D3MFExporter.cpp +++ b/code/D3MFExporter.cpp @@ -126,7 +126,6 @@ bool D3MFExporter::exportArchive( const char *file ) { return ok; } - bool D3MFExporter::exportContentTypes() { mContentOutput.clear(); @@ -177,6 +176,8 @@ bool D3MFExporter::export3DModel() { mModelOutput << "<" << XmlTag::resources << ">"; mModelOutput << std::endl; + writeBaseMaterials(); + writeObjects(); @@ -203,6 +204,10 @@ void D3MFExporter::writeHeader() { mModelOutput << std::endl; } +void D3MFExporter::writeBaseMaterials() { + +} + void D3MFExporter::writeObjects() { if ( nullptr == mScene->mRootNode ) { return; diff --git a/code/D3MFExporter.h b/code/D3MFExporter.h index 64967f68b..7e6e44e6e 100644 --- a/code/D3MFExporter.h +++ b/code/D3MFExporter.h @@ -76,6 +76,7 @@ public: protected: void writeHeader(); + void writeBaseMaterials(); void writeObjects(); void writeMesh( aiMesh *mesh ); void writeVertex( const aiVector3D &pos ); diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index fe5e260a4..7c0954524 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -70,9 +70,14 @@ namespace D3MF { class XmlSerializer { public: + using MatArray = std::vector; + using MatId2MatArray = std::map>; + XmlSerializer(XmlReader* xmlReader) : mMeshes() - , mMaterials() + , mMatArray() + , mActiveMatGroup( 99999999 ) + , mMatId2MatArray() , xmlReader(xmlReader){ // empty } @@ -109,10 +114,10 @@ public: std::copy( mMeshes.begin(), mMeshes.end(), scene->mMeshes); - scene->mNumMaterials = mMaterials.size(); + scene->mNumMaterials = mMatArray.size(); if ( 0 != scene->mNumMaterials ) { scene->mMaterials = new aiMaterial*[ scene->mNumMaterials ]; - std::copy( mMaterials.begin(), mMaterials.end(), scene->mMaterials ); + std::copy( mMatArray.begin(), mMatArray.end(), scene->mMaterials ); } scene->mRootNode->mNumChildren = static_cast(children.size()); scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren](); @@ -162,7 +167,7 @@ private: return node.release(); } - aiMesh* ReadMesh() { + aiMesh *ReadMesh() { aiMesh* mesh = new aiMesh(); while(ReadToEndElement(D3MF::XmlTag::mesh)) { if(xmlReader->getNodeName() == D3MF::XmlTag::vertices) { @@ -177,7 +182,6 @@ private: void ImportVertices(aiMesh* mesh) { std::vector vertices; - while(ReadToEndElement(D3MF::XmlTag::vertices)) { if(xmlReader->getNodeName() == D3MF::XmlTag::vertex) { vertices.push_back(ReadVertex()); @@ -234,8 +238,27 @@ private: } void ReadBaseMaterials() { + std::vector MatIdArray; + const char *baseMaterialId( xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_id.c_str() ) ); + if ( nullptr != baseMaterialId ) { + unsigned int id = std::atoi( baseMaterialId ); + const size_t newMatIdx( mMatArray.size() ); + if ( id != mActiveMatGroup ) { + mActiveMatGroup = id; + MatId2MatArray::const_iterator it( mMatId2MatArray.find( id ) ); + if ( mMatId2MatArray.end() == it ) { + MatIdArray.clear(); + mMatId2MatArray[ id ] = MatIdArray; + } else { + MatIdArray = it->second; + } + } + MatIdArray.push_back( newMatIdx ); + mMatId2MatArray[ mActiveMatGroup ] = MatIdArray; + } + while ( ReadToEndElement( D3MF::XmlTag::basematerials ) ) { - mMaterials.push_back( readMaterialDef() ); + mMatArray.push_back( readMaterialDef() ); xmlReader->read(); } } @@ -285,24 +308,37 @@ private: return true; } + void assignDiffuseColor( aiMaterial *mat ) { + const char *color = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_displaycolor.c_str() ); + aiColor4D diffuse; + if ( parseColor( color, diffuse ) ) { + mat->AddProperty( &diffuse, 1, AI_MATKEY_COLOR_DIFFUSE ); + } + + } aiMaterial *readMaterialDef() { aiMaterial *mat( nullptr ); const char *name( nullptr ); - const char *color( nullptr ); const std::string nodeName( xmlReader->getNodeName() ); if ( nodeName == D3MF::XmlTag::basematerials_base ) { name = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_name.c_str() ); - + std::string stdMatName; aiString matName; - matName.Set( name ); + std::string strId( to_string( mActiveMatGroup ) ); + stdMatName += "id"; + stdMatName += strId; + stdMatName += "_"; + if ( nullptr != name ) { + stdMatName += std::string( name ); + } else { + stdMatName += "basemat"; + } + matName.Set( stdMatName ); + mat = new aiMaterial; mat->AddProperty( &matName, AI_MATKEY_NAME ); - color = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_displaycolor.c_str() ); - aiColor4D diffuse; - if ( parseColor( color, diffuse ) ) { - mat->AddProperty( &diffuse, 1, AI_MATKEY_COLOR_DIFFUSE ); - } + assignDiffuseColor( mat ); } return mat; @@ -339,7 +375,9 @@ private: private: std::vector mMeshes; - std::vector mMaterials; + MatArray mMatArray; + unsigned int mActiveMatGroup; + MatId2MatArray mMatId2MatArray; XmlReader* xmlReader; }; @@ -370,14 +408,16 @@ D3MFImporter::~D3MFImporter() { // empty } -bool D3MFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { - const std::string extension = GetExtension(pFile); +bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool checkSig) const { + const std::string extension( GetExtension( filename ) ); if(extension == Extension ) { return true; } else if ( !extension.length() || checkSig ) { - if (nullptr == pIOHandler ) { - return true; + if ( nullptr == pIOHandler ) { + return false; } + D3MF::D3MFOpcPackage opcPackage( pIOHandler, filename ); + return opcPackage.validate(); } return false; diff --git a/code/D3MFOpcPackage.cpp b/code/D3MFOpcPackage.cpp index a7039d34e..81d610e15 100644 --- a/code/D3MFOpcPackage.cpp +++ b/code/D3MFOpcPackage.cpp @@ -247,13 +247,13 @@ private: // ------------------------------------------------------------------------------------------------ // Constructor. D3MFZipArchive::D3MFZipArchive(IOSystem* pIOHandler, const std::string& rFile) -: m_ZipFileHandle(NULL) +: m_ZipFileHandle( nullptr ) , m_ArchiveMap() { if (! rFile.empty()) { zlib_filefunc_def mapping = IOSystem2Unzip::get(pIOHandler); m_ZipFileHandle = unzOpen2(rFile.c_str(), &mapping); - if(m_ZipFileHandle != NULL) { + if(m_ZipFileHandle != nullptr ) { mapArchive(); } } @@ -267,32 +267,32 @@ D3MFZipArchive::~D3MFZipArchive() { } m_ArchiveMap.clear(); - if(m_ZipFileHandle != NULL) { + if(m_ZipFileHandle != nullptr) { unzClose(m_ZipFileHandle); - m_ZipFileHandle = NULL; + m_ZipFileHandle = nullptr; } } // ------------------------------------------------------------------------------------------------ // Returns true, if the archive is already open. bool D3MFZipArchive::isOpen() const { - return (m_ZipFileHandle != NULL); + return (m_ZipFileHandle != nullptr ); } // ------------------------------------------------------------------------------------------------ // Returns true, if the filename is part of the archive. bool D3MFZipArchive::Exists(const char* pFile) const { - ai_assert(pFile != NULL); + ai_assert(pFile != nullptr ); - bool exist = false; + if ( pFile == nullptr ) { + return false; + } - if (pFile != NULL) { - std::string rFile(pFile); - std::map::const_iterator it = m_ArchiveMap.find(rFile); - - if(it != m_ArchiveMap.end()) { - exist = true; - } + std::string rFile(pFile); + std::map::const_iterator it = m_ArchiveMap.find(rFile); + bool exist( false ); + if(it != m_ArchiveMap.end()) { + exist = true; } return exist; @@ -434,8 +434,8 @@ public: std::vector m_relationShips; }; -// ------------------------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------------------------ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile) : mRootStream(nullptr) , mZipArchive() { @@ -460,7 +460,7 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile) if ( rootFile.size() > 0 && rootFile[ 0 ] == '/' ) { rootFile = rootFile.substr( 1 ); if ( rootFile[ 0 ] == '/' ) { - // deal with zipbug + // deal with zip-bug rootFile = rootFile.substr( 1 ); } } @@ -470,18 +470,9 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile) mRootStream = mZipArchive->Open(rootFile.c_str()); ai_assert( mRootStream != nullptr ); if ( nullptr == mRootStream ) { - throw DeadlyExportError( "Cannot open rootfile in archive : " + rootFile ); + throw DeadlyExportError( "Cannot open root-file in archive : " + rootFile ); } - // const size_t size = zipArchive->FileSize(); - // m_Data.resize( size ); - - // const size_t readSize = pMapFile->Read( &m_Data[0], sizeof( char ), size ); - // if ( readSize != size ) - // { - // m_Data.clear(); - // return false; - // } mZipArchive->Close( fileStream ); } else if( file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) { @@ -498,6 +489,16 @@ IOStream* D3MFOpcPackage::RootStream() const { return mRootStream; } +static const std::string ModelRef = "3D/3dmodel.model"; + +bool D3MFOpcPackage::validate() { + if ( nullptr == mRootStream || nullptr == mZipArchive ) { + return false; + } + + return mZipArchive->Exists( ModelRef.c_str() ); +} + std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream* stream) { std::unique_ptr xmlStream(new CIrrXML_IOStreamReader(stream)); std::unique_ptr xml(irr::io::createIrrXMLReader(xmlStream.get())); @@ -508,14 +509,14 @@ std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream* stream) { return rel->type == XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE; }); - if(itr == reader.m_relationShips.end()) - throw DeadlyImportError("Cannot find " + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE); + if ( itr == reader.m_relationShips.end() ) { + throw DeadlyImportError( "Cannot find " + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE ); + } return (*itr)->target; } } // Namespace D3MF - } // Namespace Assimp #endif //ASSIMP_BUILD_NO_3MF_IMPORTER diff --git a/code/D3MFOpcPackage.h b/code/D3MFOpcPackage.h index 8cf08d092..b49740eff 100644 --- a/code/D3MFOpcPackage.h +++ b/code/D3MFOpcPackage.h @@ -51,8 +51,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { namespace D3MF { -typedef irr::io::IrrXMLReader XmlReader; -typedef std::shared_ptr XmlReaderPtr; +using XmlReader = irr::io::IrrXMLReader ; +using XmlReaderPtr = std::shared_ptr ; struct OpcPackageRelationship { std::string id; @@ -67,6 +67,7 @@ public: D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile); ~D3MFOpcPackage(); IOStream* RootStream() const; + bool validate(); protected: std::string ReadPackageRootRelationship(IOStream* stream); @@ -76,7 +77,7 @@ private: std::unique_ptr mZipArchive; }; -} -} +} // Namespace D3MF +} // Namespace Assimp #endif // D3MFOPCPACKAGE_H From 6668eeb68eaeeff2b0686d07d7ec6e1cdf88c882 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 9 Mar 2018 19:03:05 +0100 Subject: [PATCH 076/278] Fix possible nullptr dereferencing. --- code/D3MFExporter.cpp | 42 ++++++++++++++++++++++++++++++++++++-- include/assimp/fast_atof.h | 2 -- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/code/D3MFExporter.cpp b/code/D3MFExporter.cpp index a74280af7..98b15b10b 100644 --- a/code/D3MFExporter.cpp +++ b/code/D3MFExporter.cpp @@ -49,8 +49,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include - +#include #include + #include "3MFXmlTags.h" #include "D3MFOpcPackage.h" @@ -204,8 +205,45 @@ void D3MFExporter::writeHeader() { mModelOutput << std::endl; } -void D3MFExporter::writeBaseMaterials() { +static std::string to_hex( int to_convert ) { + std::string result; + std::stringstream ss; + ss << std::hex << to_convert; + ss >> result; + return result; +} +void D3MFExporter::writeBaseMaterials() { + mModelOutput << "\n"; + for ( size_t i = 0; i < mScene->mNumMaterials; ++i ) { + aiMaterial *mat = mScene->mMaterials[ i ]; + std::string strName; + aiString name; + if ( mat->Get( AI_MATKEY_NAME, name ) != aiReturn_SUCCESS ) { + strName = "basemat_" + to_string( i ); + } else { + strName = name.C_Str(); + } + std::string hexDiffuseColor; + aiColor4D color; + if ( mat->Get( AI_MATKEY_COLOR_DIFFUSE, color ) == aiReturn_SUCCESS ) { + hexDiffuseColor = "#"; + std::string tmp; + tmp = to_hex( color.r ); + hexDiffuseColor += tmp; + tmp = to_hex( color.g ); + hexDiffuseColor += tmp; + tmp = to_hex( color.b ); + hexDiffuseColor += tmp; + tmp = to_hex( color.a ); + hexDiffuseColor += tmp; + } else { + hexDiffuseColor = "#FFFFFFFF"; + } + + mModelOutput << "\n"; + } + mModelOutput << "\n"; } void D3MFExporter::writeObjects() { diff --git a/include/assimp/fast_atof.h b/include/assimp/fast_atof.h index fced5307a..e66f1b37d 100644 --- a/include/assimp/fast_atof.h +++ b/include/assimp/fast_atof.h @@ -146,7 +146,6 @@ uint8_t HexOctetToDecimal(const char* in) { return ((uint8_t)HexDigitToDecimal(in[0])<<4)+(uint8_t)HexDigitToDecimal(in[1]); } - // ------------------------------------------------------------------------------------ // signed variant of strtoul10 // ------------------------------------------------------------------------------------ @@ -353,7 +352,6 @@ ai_real fast_atof(const char* c) { return ret; } - inline ai_real fast_atof( const char* c, const char** cout) { ai_real ret(0.0); From 336a09ee0e47f5520eb3032d7b377982176fbe6d Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 9 Mar 2018 23:35:12 +0100 Subject: [PATCH 077/278] add material reference to faces. --- code/ConvertToLHProcess.cpp | 26 +++++++++++++++++--------- code/D3MFExporter.cpp | 9 ++++++--- code/D3MFExporter.h | 2 +- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/code/ConvertToLHProcess.cpp b/code/ConvertToLHProcess.cpp index 47e2fb949..ba8371439 100644 --- a/code/ConvertToLHProcess.cpp +++ b/code/ConvertToLHProcess.cpp @@ -91,12 +91,14 @@ void MakeLeftHandedProcess::Execute( aiScene* pScene) ProcessNode( pScene->mRootNode, aiMatrix4x4()); // process the meshes accordingly - for( unsigned int a = 0; a < pScene->mNumMeshes; ++a) - ProcessMesh( pScene->mMeshes[a]); + for ( unsigned int a = 0; a < pScene->mNumMeshes; ++a ) { + ProcessMesh( pScene->mMeshes[ a ] ); + } // process the materials accordingly - for( unsigned int a = 0; a < pScene->mNumMaterials; ++a) - ProcessMaterial( pScene->mMaterials[a]); + for ( unsigned int a = 0; a < pScene->mNumMaterials; ++a ) { + ProcessMaterial( pScene->mMaterials[ a ] ); + } // transform all animation channels as well for( unsigned int a = 0; a < pScene->mNumAnimations; a++) @@ -136,8 +138,11 @@ void MakeLeftHandedProcess::ProcessNode( aiNode* pNode, const aiMatrix4x4& pPare // ------------------------------------------------------------------------------------------------ // Converts a single mesh to left handed coordinates. -void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) -{ +void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) { + if ( nullptr == pMesh ) { + DefaultLogger::get()->error( "Nullptr to mesh found." ); + return; + } // mirror positions, normals and stuff along the Z axis for( size_t a = 0; a < pMesh->mNumVertices; ++a) { @@ -173,8 +178,12 @@ void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) // ------------------------------------------------------------------------------------------------ // Converts a single material to left handed coordinates. -void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat) -{ +void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat) { + if ( nullptr == _mat ) { + DefaultLogger::get()->error( "Nullptr to aiMaterial found." ); + return; + } + aiMaterial* mat = (aiMaterial*)_mat; for (unsigned int a = 0; a < mat->mNumProperties;++a) { aiMaterialProperty* prop = mat->mProperties[a]; @@ -183,7 +192,6 @@ void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat) if (!::strcmp( prop->mKey.data, "$tex.mapaxis")) { ai_assert( prop->mDataLength >= sizeof(aiVector3D)); /* something is wrong with the validation if we end up here */ aiVector3D* pff = (aiVector3D*)prop->mData; - pff->z *= -1.f; } } diff --git a/code/D3MFExporter.cpp b/code/D3MFExporter.cpp index 98b15b10b..7c75178e6 100644 --- a/code/D3MFExporter.cpp +++ b/code/D3MFExporter.cpp @@ -285,7 +285,9 @@ void D3MFExporter::writeMesh( aiMesh *mesh ) { } mModelOutput << "" << std::endl; - writeFaces( mesh ); + const unsigned int matIdx( mesh->mMaterialIndex ); + + writeFaces( mesh, matIdx ); mModelOutput << "" << std::endl; } @@ -295,7 +297,7 @@ void D3MFExporter::writeVertex( const aiVector3D &pos ) { mModelOutput << std::endl; } -void D3MFExporter::writeFaces( aiMesh *mesh ) { +void D3MFExporter::writeFaces( aiMesh *mesh, unsigned int matIdx ) { if ( nullptr == mesh ) { return; } @@ -307,7 +309,8 @@ void D3MFExporter::writeFaces( aiMesh *mesh ) { for ( unsigned int i = 0; i < mesh->mNumFaces; ++i ) { aiFace ¤tFace = mesh->mFaces[ i ]; mModelOutput << "<" << XmlTag::triangle << " v1=\"" << currentFace.mIndices[ 0 ] << "\" v2=\"" - << currentFace.mIndices[ 1 ] << "\" v3=\"" << currentFace.mIndices[ 2 ] << "\"/>"; + << currentFace.mIndices[ 1 ] << "\" v3=\"" << currentFace.mIndices[ 2 ] + << "\" pid=\"1\" p1=\""+to_string(matIdx)+"\" />"; mModelOutput << std::endl; } mModelOutput << ""; diff --git a/code/D3MFExporter.h b/code/D3MFExporter.h index 7e6e44e6e..b553e0ab5 100644 --- a/code/D3MFExporter.h +++ b/code/D3MFExporter.h @@ -80,7 +80,7 @@ protected: void writeObjects(); void writeMesh( aiMesh *mesh ); void writeVertex( const aiVector3D &pos ); - void writeFaces( aiMesh *mesh ); + void writeFaces( aiMesh *mesh, unsigned int matIdx ); void writeBuild(); void exportContentTyp( const std::string &filename ); void writeModelToArchive( const std::string &folder, const std::string &modelName ); From 017b7d1a2f51a4f62047c98f987704fc9fabebe4 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 11 Mar 2018 20:15:25 +0100 Subject: [PATCH 078/278] 3MF: add missig tags for meta data. --- code/3MFXmlTags.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/code/3MFXmlTags.h b/code/3MFXmlTags.h index feedf4538..e869c33c1 100644 --- a/code/3MFXmlTags.h +++ b/code/3MFXmlTags.h @@ -45,6 +45,10 @@ namespace Assimp { namespace D3MF { namespace XmlTag { + // Meta-data + static const std::string meta = "metadata"; + static const std::string meta_name = "name"; + // Model-data specific tags static const std::string model = "model"; static const std::string model_unit = "unit"; From c8ae0bbb3d43384fde27c28c93343b0f885dc5e8 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 11 Mar 2018 20:15:49 +0100 Subject: [PATCH 079/278] 3MF: fix model folder desc. --- code/D3MFExporter.cpp | 25 +++++++++++-------------- code/D3MFImporter.cpp | 6 ++---- include/assimp/StringUtils.h | 36 +++++++++++++++++++++++++++++++++--- 3 files changed, 46 insertions(+), 21 deletions(-) diff --git a/code/D3MFExporter.cpp b/code/D3MFExporter.cpp index 7c75178e6..b89e81ce6 100644 --- a/code/D3MFExporter.cpp +++ b/code/D3MFExporter.cpp @@ -153,7 +153,11 @@ bool D3MFExporter::exportRelations() { mRelOutput << ""; for ( size_t i = 0; i < mRelations.size(); ++i ) { - mRelOutput << "target << "\" "; + if ( mRelations[ i ]->target[ 0 ] == '/' ) { + mRelOutput << "target << "\" "; + } else { + mRelOutput << "target << "\" "; + } mRelOutput << "Id=\"" << mRelations[i]->id << "\" "; mRelOutput << "Type=\"" << mRelations[ i ]->type << "\" />"; mRelOutput << std::endl; @@ -205,14 +209,6 @@ void D3MFExporter::writeHeader() { mModelOutput << std::endl; } -static std::string to_hex( int to_convert ) { - std::string result; - std::stringstream ss; - ss << std::hex << to_convert; - ss >> result; - return result; -} - void D3MFExporter::writeBaseMaterials() { mModelOutput << "\n"; for ( size_t i = 0; i < mScene->mNumMaterials; ++i ) { @@ -229,19 +225,20 @@ void D3MFExporter::writeBaseMaterials() { if ( mat->Get( AI_MATKEY_COLOR_DIFFUSE, color ) == aiReturn_SUCCESS ) { hexDiffuseColor = "#"; std::string tmp; - tmp = to_hex( color.r ); + + tmp = DecimalToHexa( color.r ); hexDiffuseColor += tmp; - tmp = to_hex( color.g ); + tmp = DecimalToHexa( color.g ); hexDiffuseColor += tmp; - tmp = to_hex( color.b ); + tmp = DecimalToHexa( color.b ); hexDiffuseColor += tmp; - tmp = to_hex( color.a ); + tmp = DecimalToHexa( color.a ); hexDiffuseColor += tmp; } else { hexDiffuseColor = "#FFFFFFFF"; } - mModelOutput << "\n"; + mModelOutput << "\n"; } mModelOutput << "\n"; } diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index 7c0954524..1732a5a8a 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -259,7 +259,6 @@ private: while ( ReadToEndElement( D3MF::XmlTag::basematerials ) ) { mMatArray.push_back( readMaterialDef() ); - xmlReader->read(); } } @@ -398,7 +397,6 @@ static const aiImporterDesc desc = { Extension.c_str() }; - D3MFImporter::D3MFImporter() : BaseImporter() { // empty @@ -431,8 +429,8 @@ const aiImporterDesc *D3MFImporter::GetInfo() const { return &desc; } -void D3MFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { - D3MF::D3MFOpcPackage opcPackage(pIOHandler, pFile); +void D3MFImporter::InternReadFile( const std::string &filename, aiScene *pScene, IOSystem *pIOHandler ) { + D3MF::D3MFOpcPackage opcPackage(pIOHandler, filename); std::unique_ptr xmlStream(new CIrrXML_IOStreamReader(opcPackage.RootStream())); std::unique_ptr xmlReader(irr::io::createIrrXMLReader(xmlStream.get())); diff --git a/include/assimp/StringUtils.h b/include/assimp/StringUtils.h index 3c3afd264..157454126 100644 --- a/include/assimp/StringUtils.h +++ b/include/assimp/StringUtils.h @@ -55,7 +55,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /// @return The number of written characters if the buffer size was big enough. If an encoding error occurs, a negative number is returned. #if defined(_MSC_VER) && _MSC_VER < 1900 - inline int c99_ai_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) { + inline + int c99_ai_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) { int count(-1); if (0 != size) { count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap); @@ -67,7 +68,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return count; } - inline int ai_snprintf(char *outBuf, size_t size, const char *format, ...) { + inline + int ai_snprintf(char *outBuf, size_t size, const char *format, ...) { int count; va_list ap; @@ -82,14 +84,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # define ai_snprintf snprintf #endif +/// @fn to_string +/// @brief The portable version of to_string ( some gcc-versions on embedded devices are not supporting this). +/// @param value The value to write into the std::string. +/// @return The value as a std::string template inline std::string to_string( T value ) { std::ostringstream os; os << value; + return os.str(); } +/// @fn ai_strtof +/// @brief The portable version of strtof. +/// @param begin The first character of the string. +/// @param end The last character +/// @return The float value, 0.0f in cas of an error. inline float ai_strtof( const char *begin, const char *end ) { if ( nullptr == begin ) { @@ -107,5 +119,23 @@ float ai_strtof( const char *begin, const char *end ) { return val; } -#endif // INCLUDED_AI_STRINGUTILS_H +/// @fn DecimalToHexa +/// @brief The portable to convert a decimal value into a hexadecimal string. +/// @param toConvert Value to convert +/// @return The hexadecimal string, is empty in case of an error. +template +inline +std::string DecimalToHexa( T toConvert ) { + std::string result; + std::stringstream ss; + ss << std::hex << toConvert; + ss >> result; + for ( size_t i = 0; i < result.size(); ++i ) { + result[ i ] = toupper( result[ i ] ); + } + + return result; +} + +#endif // INCLUDED_AI_STRINGUTILS_H From c7ac32f891a16cc49fcca9b656feec75c116de76 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 12 Mar 2018 22:28:00 +0100 Subject: [PATCH 080/278] fix naming readout + export. --- code/D3MFImporter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index 1732a5a8a..fce2743fe 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -133,11 +133,11 @@ private: const char *attrib( nullptr ); std::string name, type; - attrib = xmlReader->getAttributeValue( D3MF::XmlTag::name.c_str() ); + attrib = xmlReader->getAttributeValue( D3MF::XmlTag::id.c_str() ); if ( nullptr != attrib ) { name = attrib; } - attrib = xmlReader->getAttributeValue( D3MF::XmlTag::name.c_str() ); + attrib = xmlReader->getAttributeValue( D3MF::XmlTag::type.c_str() ); if ( nullptr != attrib ) { type = attrib; } From f11d4902c626e08a949f83eefcb38483c3edc5e9 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 13 Mar 2018 17:50:34 +0100 Subject: [PATCH 081/278] fix CanRead-method for the 3MF-Importer. --- code/D3MFImporter.cpp | 3 +++ code/D3MFOpcPackage.cpp | 9 +++++++++ code/D3MFOpcPackage.h | 3 ++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index fce2743fe..c5b4a8c91 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -414,6 +414,9 @@ bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bo if ( nullptr == pIOHandler ) { return false; } + if ( !D3MF::D3MFOpcPackage::isZipArchive( pIOHandler, filename ) ) { + return false; + } D3MF::D3MFOpcPackage opcPackage( pIOHandler, filename ); return opcPackage.validate(); } diff --git a/code/D3MFOpcPackage.cpp b/code/D3MFOpcPackage.cpp index 81d610e15..2f7c8a25e 100644 --- a/code/D3MFOpcPackage.cpp +++ b/code/D3MFOpcPackage.cpp @@ -499,6 +499,15 @@ bool D3MFOpcPackage::validate() { return mZipArchive->Exists( ModelRef.c_str() ); } +bool D3MFOpcPackage::isZipArchive( IOSystem* pIOHandler, const std::string& rFile ) { + D3MF::D3MFZipArchive ar( pIOHandler, rFile ); + if ( !ar.isOpen() ) { + return false; + } + + return true; +} + std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream* stream) { std::unique_ptr xmlStream(new CIrrXML_IOStreamReader(stream)); std::unique_ptr xml(irr::io::createIrrXMLReader(xmlStream.get())); diff --git a/code/D3MFOpcPackage.h b/code/D3MFOpcPackage.h index b49740eff..6d7b3d478 100644 --- a/code/D3MFOpcPackage.h +++ b/code/D3MFOpcPackage.h @@ -64,10 +64,11 @@ class D3MFZipArchive; class D3MFOpcPackage { public: - D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile); + D3MFOpcPackage( IOSystem* pIOHandler, const std::string& rFile ); ~D3MFOpcPackage(); IOStream* RootStream() const; bool validate(); + static bool isZipArchive( IOSystem* pIOHandler, const std::string& rFile ); protected: std::string ReadPackageRootRelationship(IOStream* stream); From 6b9add5594185afdc90f58c385bb78cf7699fa70 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 13 Mar 2018 18:19:10 +0100 Subject: [PATCH 082/278] fix compiler warning fr 64 bit --- code/D3MFImporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index c5b4a8c91..3fffa5aeb 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -114,7 +114,7 @@ public: std::copy( mMeshes.begin(), mMeshes.end(), scene->mMeshes); - scene->mNumMaterials = mMatArray.size(); + scene->mNumMaterials = static_cast( mMatArray.size() ); if ( 0 != scene->mNumMaterials ) { scene->mMaterials = new aiMaterial*[ scene->mNumMaterials ]; std::copy( mMatArray.begin(), mMatArray.end(), scene->mMaterials ); From f857d72dbbb07177e80f80af639f1c7e685f7ddd Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 13 Mar 2018 18:56:47 +0100 Subject: [PATCH 083/278] add roundtrip test for 3mf. --- test/unit/utD3MFImportExport.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/unit/utD3MFImportExport.cpp b/test/unit/utD3MFImportExport.cpp index 3aefeba84..dd54b3042 100644 --- a/test/unit/utD3MFImportExport.cpp +++ b/test/unit/utD3MFImportExport.cpp @@ -86,4 +86,11 @@ TEST_F( utD3MFImporterExporter, export3MFtoMemTest ) { EXPECT_TRUE( exporterTest() ); } +TEST_F( utD3MFImporterExporter, roundtrip3MFtoMemTest ) { + EXPECT_TRUE( exporterTest() ); + + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "test.3mf", 0 ); +} + #endif // ASSIMP_BUILD_NO_EXPORT From 18e9aa13d6a603983e25675bb7a376caf45c3c02 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 13 Mar 2018 19:15:56 +0100 Subject: [PATCH 084/278] fix vs2017-compiler-warning c4002: tr1 is deprecated. --- test/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a9dfaf83f..049dbcdd2 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -45,7 +45,9 @@ INCLUDE_DIRECTORIES( ${Assimp_SOURCE_DIR}/include ${Assimp_SOURCE_DIR}/code ) - +if (MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING") +endif() # Add the temporary output directories to the library path to make sure the # Assimp library can be found, even if it is not installed system-wide yet. LINK_DIRECTORIES( ${Assimp_BINARY_DIR} ${AssetImporter_BINARY_DIR}/lib ) From 20c817bc36e9f7cc16abbba8a0b613de910faf43 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 13 Mar 2018 19:42:06 +0100 Subject: [PATCH 085/278] Update utD3MFImportExport.cpp Fix compiler warning: unused var. --- test/unit/utD3MFImportExport.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/unit/utD3MFImportExport.cpp b/test/unit/utD3MFImportExport.cpp index dd54b3042..e8797d74d 100644 --- a/test/unit/utD3MFImportExport.cpp +++ b/test/unit/utD3MFImportExport.cpp @@ -91,6 +91,7 @@ TEST_F( utD3MFImporterExporter, roundtrip3MFtoMemTest ) { Assimp::Importer importer; const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "test.3mf", 0 ); + EXPECT_NE( nullptr, scene ); } #endif // ASSIMP_BUILD_NO_EXPORT From 4c023c3818252c1102c5dc2bca200d0a9fff9d8b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 13 Mar 2018 21:40:23 +0100 Subject: [PATCH 086/278] fix unittest folder for roundtriptest. --- code/IRRLoader.cpp | 20 ++++++++------------ test/unit/utD3MFImportExport.cpp | 2 +- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/code/IRRLoader.cpp b/code/IRRLoader.cpp index fbec3da00..66d15c5c4 100644 --- a/code/IRRLoader.cpp +++ b/code/IRRLoader.cpp @@ -100,26 +100,22 @@ IRRImporter::~IRRImporter() // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool IRRImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - /* NOTE: A simple check for the file extension is not enough - * here. Irrmesh and irr are easy, but xml is too generic - * and could be collada, too. So we need to open the file and - * search for typical tokens. - */ +bool IRRImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const { const std::string extension = GetExtension(pFile); - - if (extension == "irr")return true; - else if (extension == "xml" || checkSig) - { + if ( extension == "irr" ) { + return true; + } else if (extension == "xml" || checkSig) { /* If CanRead() is called in order to check whether we * support a specific file extension in general pIOHandler * might be NULL and it's our duty to return true here. */ - if (!pIOHandler)return true; + if ( nullptr == pIOHandler ) { + return true; + } const char* tokens[] = {"irr_scene"}; return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); } + return false; } diff --git a/test/unit/utD3MFImportExport.cpp b/test/unit/utD3MFImportExport.cpp index e8797d74d..c5fdd003b 100644 --- a/test/unit/utD3MFImportExport.cpp +++ b/test/unit/utD3MFImportExport.cpp @@ -90,7 +90,7 @@ TEST_F( utD3MFImporterExporter, roundtrip3MFtoMemTest ) { EXPECT_TRUE( exporterTest() ); Assimp::Importer importer; - const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "test.3mf", 0 ); + const aiScene *scene = importer.ReadFile( "test.3mf", 0 ); EXPECT_NE( nullptr, scene ); } From 5cf6509fb51c648a2c155ed82920a7ae2947ea2d Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 14 Mar 2018 20:42:42 +0100 Subject: [PATCH 087/278] closes https://github.com/assimp/assimp/issues/1120: use euler angles for pre- and post-rotation. --- code/FBXConverter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 5d732c7b2..9bb023b4e 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -643,14 +643,14 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector if ( ok && PreRotation.SquareLength() > zero_epsilon ) { is_complex = true; - GetRotationMatrix( rot, PreRotation, chain[ TransformationComp_PreRotation ] ); + GetRotationMatrix( Model::RotOrder::RotOrder_EulerXYZ, PreRotation, chain[ TransformationComp_PreRotation ] ); } const aiVector3D& PostRotation = PropertyGet( props, "PostRotation", ok ); if ( ok && PostRotation.SquareLength() > zero_epsilon ) { is_complex = true; - GetRotationMatrix( rot, PostRotation, chain[ TransformationComp_PostRotation ] ); + GetRotationMatrix( Model::RotOrder::RotOrder_EulerXYZ, PostRotation, chain[ TransformationComp_PostRotation ] ); } const aiVector3D& RotationPivot = PropertyGet( props, "RotationPivot", ok ); From 2d980c16f0359c3c2e78bd71c86627aa97c705b0 Mon Sep 17 00:00:00 2001 From: Sergey Gonchar Date: Thu, 15 Mar 2018 21:41:40 -0700 Subject: [PATCH 088/278] Support Maya 2018 Collada Export with blendshapes and bones controllers for a mesh --- code/ColladaParser.cpp | 16 ++++++++++++++++ code/ColladaParser.h | 3 +++ 2 files changed, 19 insertions(+) diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index d62c5cafc..d96ac0d39 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -222,6 +222,7 @@ void ColladaParser::ReadStructure() } PostProcessRootAnimations(); + PostProcessControllers(); } // ------------------------------------------------------------------------------------------------ @@ -360,6 +361,21 @@ void ColladaParser::ReadAnimationClipLibrary() } } +void ColladaParser::PostProcessControllers() +{ + for (ControllerLibrary::iterator it = mControllerLibrary.begin(); it != mControllerLibrary.end(); ++it) + { + std::string meshId = it->second.mMeshId; + ControllerLibrary::iterator findItr = mControllerLibrary.find(meshId); + while(findItr != mControllerLibrary.end()) { + meshId = findItr->second.mMeshId; + findItr = mControllerLibrary.find(meshId); + } + + it->second.mMeshId = meshId; + } +} + // ------------------------------------------------------------------------------------------------ // Re-build animations from animation clip library, if present, otherwise combine single-channel animations void ColladaParser::PostProcessRootAnimations() diff --git a/code/ColladaParser.h b/code/ColladaParser.h index 566386840..21f741551 100644 --- a/code/ColladaParser.h +++ b/code/ColladaParser.h @@ -87,6 +87,9 @@ namespace Assimp /** Reads the animation clip library */ void ReadAnimationClipLibrary(); + /** Unwrap controllers dependency hierarchy */ + void PostProcessControllers(); + /** Re-build animations from animation clip library, if present, otherwise combine single-channel animations */ void PostProcessRootAnimations(); From ef2343506b3f5d279f8408af1d7129777e02ef08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20L=C3=B6ber?= Date: Fri, 16 Mar 2018 11:17:28 +0100 Subject: [PATCH 089/278] Expand the current description about loading of embedded textures --- doc/dox.h | 51 +++++++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/doc/dox.h b/doc/dox.h index d9462590b..067592438 100644 --- a/doc/dox.h +++ b/doc/dox.h @@ -667,27 +667,31 @@ need them at all. Normally textures used by assets are stored in separate files, however, there are file formats embedding their textures directly into the model file. Such textures are loaded into an aiTexture structure. -For embedded textures, the value of `AI_MATKEY_TEXTURE(textureType, index)` will be `*` where -`` is the index of the texture in aiScene::mTextures. -
+ +In previous versions, the path from the query for `AI_MATKEY_TEXTURE(textureType, index)` would be +`*` where `` is the index of the texture in aiScene::mTextures. Now this call will +return a file path for embedded textures in FBX files. To test if it is an embdedded texture use +aiScene::GetEmbeddedTexture. If the returned pointer is not null, it is embedded und can be loaded +from the data structure. If it is null, search for a separate file. Other file types still use the +old behaviour.
+If your rely on the old behaviour, you can use Assimp::Importer::SetPropertyBool with the key +#AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING to force the old behaviour. + There are two cases: -
-1) The texture is NOT compressed. Its color data is directly stored -in the aiTexture structure as an array of aiTexture::mWidth * aiTexture::mHeight aiTexel structures. Each aiTexel represents a pixel (or "texel") of the texture -image. The color data is stored in an unsigned RGBA8888 format, which can be easily used for -both Direct3D and OpenGL (swizzling the order of the color components might be necessary). -RGBA8888 has been chosen because it is well-known, easy to use and natively -supported by nearly all graphics APIs. -
-2) This applies if aiTexture::mHeight == 0 is fulfilled. Then, texture is stored in a -"compressed" format such as DDS or PNG. The term "compressed" does not mean that the -texture data must actually be compressed, however the texture was found in the -model file as if it was stored in a separate file on the harddisk. Appropriate -decoders (such as libjpeg, libpng, D3DX, DevIL) are required to load theses textures. -aiTexture::mWidth specifies the size of the texture data in bytes, aiTexture::pcData is -a pointer to the raw image data and aiTexture::achFormatHint is either zeroed or -contains the most common file extension of the embedded texture's format. This value is only -set if assimp is able to determine the file format. +1. The texture is NOT compressed. Its color data is directly stored in the aiTexture structure as an + array of aiTexture::mWidth * aiTexture::mHeight aiTexel structures. Each aiTexel represents a + pixel (or "texel") of the texture image. The color data is stored in an unsigned RGBA8888 format, + which can be easily used for both Direct3D and OpenGL (swizzling the order of the color + components might be necessary). RGBA8888 has been chosen because it is well-known, easy to use + and natively supported by nearly all graphics APIs. +2. This applies if aiTexture::mHeight == 0 is fulfilled. Then, texture is stored in a "compressed" + format such as DDS or PNG. The term "compressed" does not mean that the texture data must + actually be compressed, however the texture was found in the model file as if it was stored in a + separate file on the harddisk. Appropriate decoders (such as libjpeg, libpng, D3DX, DevIL) are + required to load theses textures. aiTexture::mWidth specifies the size of the texture data in + bytes, aiTexture::pcData is a pointer to the raw image data and aiTexture::achFormatHint is + either zeroed or contains the most common file extension of the embedded texture's format. This + value is only set if assimp is able to determine the file format. */ @@ -871,8 +875,11 @@ All material key constants start with 'AI_MATKEY' (it's an ugly macro for histor TEXTURE(t,n) aiString n/a - Defines the path of the n'th texture on the stack 't', where 'n' is any value >= 0 and 't' is one of the #aiTextureType enumerated values. Either a filepath or `*`, where `` is the index of an embedded texture in aiScene::mTextures. - See the 'Textures' section above. + Defines the path of the n'th texture on the stack 't', where 'n' is any value >= 0 and 't' + is one of the #aiTextureType enumerated values. A file path to an external file or an embedded + texture. Use aiScene::GetEmbeddedTexture to test if it is embedded for FBX files, in other cases + embedded textures start with '*' followed by an index into aiScene::mTextures. + See the @ref mat_tex section above. Also see @ref textures for a more information about texture retrieval. From 9d813a48b00b23518519c179a10993c1dcb6a40c Mon Sep 17 00:00:00 2001 From: Marco Di Benedetto Date: Mon, 19 Mar 2018 18:22:27 +0100 Subject: [PATCH 090/278] fixed emply buffer stream write, removed some cast warnings. --- code/D3MFImporter.cpp | 2 +- code/DefaultIOSystem.cpp | 6 ++--- code/EmbedTexturesProcess.cpp | 12 ++++----- code/FBXConverter.cpp | 6 ++--- code/FBXExportNode.cpp | 16 +++++------ code/FBXExportProperty.cpp | 14 +++++----- code/FBXExporter.cpp | 50 +++++++++++++++++------------------ code/XFileParser.cpp | 4 +-- include/assimp/StreamWriter.h | 4 +-- 9 files changed, 57 insertions(+), 57 deletions(-) diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index 3fffa5aeb..764f0d28b 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -253,7 +253,7 @@ private: MatIdArray = it->second; } } - MatIdArray.push_back( newMatIdx ); + MatIdArray.push_back( (unsigned int)newMatIdx ); mMatId2MatArray[ mActiveMatGroup ] = MatIdArray; } diff --git a/code/DefaultIOSystem.cpp b/code/DefaultIOSystem.cpp index 5e50be8bd..6e9c0321e 100644 --- a/code/DefaultIOSystem.cpp +++ b/code/DefaultIOSystem.cpp @@ -76,7 +76,7 @@ bool DefaultIOSystem::Exists( const char* pFile) const #ifdef _WIN32 wchar_t fileName16[PATHLIMIT]; - bool isUnicode = IsTextUnicode(pFile, strlen(pFile), NULL); + bool isUnicode = IsTextUnicode(pFile, int(strlen(pFile)), NULL); if (isUnicode) { MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, pFile, -1, fileName16, PATHLIMIT); @@ -110,7 +110,7 @@ IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode) FILE* file; #ifdef _WIN32 wchar_t fileName16[PATHLIMIT]; - bool isUnicode = IsTextUnicode(strFile, strlen(strFile), NULL ); + bool isUnicode = IsTextUnicode(strFile, int(strlen(strFile)), NULL ); if (isUnicode) { MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, strFile, -1, fileName16, PATHLIMIT); std::string mode8(strMode); @@ -158,7 +158,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out) { ai_assert(in && _out); #if defined( _MSC_VER ) || defined( __MINGW32__ ) - bool isUnicode = IsTextUnicode(in, strlen(in), NULL); + bool isUnicode = IsTextUnicode(in, int(strlen(in)), NULL); if (isUnicode) { wchar_t out16[PATHLIMIT]; wchar_t in16[PATHLIMIT]; diff --git a/code/EmbedTexturesProcess.cpp b/code/EmbedTexturesProcess.cpp index addfb9746..b434d79d7 100644 --- a/code/EmbedTexturesProcess.cpp +++ b/code/EmbedTexturesProcess.cpp @@ -99,22 +99,22 @@ void EmbedTexturesProcess::Execute(aiScene* pScene) { } bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const { - uint32_t imageSize = 0; - std::string imagePath = path; + std::streampos imageSize = 0; + std::string imagePath = path; // Test path directly std::ifstream file(imagePath, std::ios::binary | std::ios::ate); - if ((imageSize = file.tellg()) == -1u) { + if ((imageSize = file.tellg()) == std::streampos(-1)) { DefaultLogger::get()->warn("EmbedTexturesProcess: Cannot find image: " + imagePath + ". Will try to find it in root folder."); // Test path in root path imagePath = mRootPath + path; file.open(imagePath, std::ios::binary | std::ios::ate); - if ((imageSize = file.tellg()) == -1u) { + if ((imageSize = file.tellg()) == std::streampos(-1)) { // Test path basename in root path imagePath = mRootPath + path.substr(path.find_last_of("\\/") + 1u); file.open(imagePath, std::ios::binary | std::ios::ate); - if ((imageSize = file.tellg()) == -1u) { + if ((imageSize = file.tellg()) == std::streampos(-1)) { DefaultLogger::get()->error("EmbedTexturesProcess: Unable to embed texture: " + path + "."); return false; } @@ -134,7 +134,7 @@ bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const { // Add the new texture auto pTexture = new aiTexture(); pTexture->mHeight = 0; // Means that this is still compressed - pTexture->mWidth = imageSize; + pTexture->mWidth = uint32_t(imageSize); pTexture->pcData = imageContent; auto extension = path.substr(path.find_last_of('.') + 1u); diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 9bb023b4e..16874df69 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -704,7 +704,7 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector aiMatrix4x4::Scaling( GeometricScaling, chain[ TransformationComp_GeometricScaling ] ); aiVector3D GeometricScalingInverse = GeometricScaling; bool canscale = true; - for (size_t i = 0; i < 3; ++i) { + for (unsigned int i = 0; i < 3; ++i) { if ( std::fabs( GeometricScalingInverse[i] ) > zero_epsilon ) { GeometricScalingInverse[i] = 1.0f / GeometricScaling[i]; } else { @@ -1888,11 +1888,11 @@ void Converter::SetShadingPropertiesCommon( aiMaterial* out_mat, const PropertyT // TransparentColor / TransparencyFactor... gee thanks FBX :rolleyes: const aiColor3D& Transparent = GetColorPropertyFactored( props, "TransparentColor", "TransparencyFactor", ok ); - float CalculatedOpacity = 1.0; + float CalculatedOpacity = 1.0f; if ( ok ) { out_mat->AddProperty( &Transparent, 1, AI_MATKEY_COLOR_TRANSPARENT ); // as calculated by FBX SDK 2017: - CalculatedOpacity = 1.0 - ((Transparent.r + Transparent.g + Transparent.b) / 3.0); + CalculatedOpacity = 1.0f - ((Transparent.r + Transparent.g + Transparent.b) / 3.0f); } // use of TransparencyFactor is inconsistent. diff --git a/code/FBXExportNode.cpp b/code/FBXExportNode.cpp index f218f068d..596901989 100644 --- a/code/FBXExportNode.cpp +++ b/code/FBXExportNode.cpp @@ -182,7 +182,7 @@ void FBX::Node::Begin(Assimp::StreamWriterLE &s) s.PutU4(0); // total property section length // node name - s.PutU1(name.size()); // length of node name + s.PutU1(uint8_t(name.size())); // length of node name s.PutString(name); // node name as raw bytes // property data comes after here @@ -217,8 +217,8 @@ void FBX::Node::EndProperties( ai_assert(pos > property_start); size_t property_section_size = pos - property_start; s.Seek(start_pos + 4); - s.PutU4(num_properties); - s.PutU4(property_section_size); + s.PutU4(uint32_t(num_properties)); + s.PutU4(uint32_t(property_section_size)); s.Seek(pos); } @@ -232,7 +232,7 @@ void FBX::Node::End( // now go back and write initial pos this->end_pos = s.Tell(); s.Seek(start_pos); - s.PutU4(end_pos); + s.PutU4(uint32_t(end_pos)); s.Seek(end_pos); } @@ -251,9 +251,9 @@ void FBX::Node::WritePropertyNode( Node node(name); node.Begin(s); s.PutU1('d'); - s.PutU4(v.size()); // number of elements + s.PutU4(uint32_t(v.size())); // number of elements s.PutU4(0); // no encoding (1 would be zip-compressed) - s.PutU4(v.size() * 8); // data size + s.PutU4(uint32_t(v.size()) * 8); // data size for (auto it = v.begin(); it != v.end(); ++it) { s.PutF8(*it); } node.EndProperties(s, 1); node.End(s, false); @@ -271,9 +271,9 @@ void FBX::Node::WritePropertyNode( Node node(name); node.Begin(s); s.PutU1('i'); - s.PutU4(v.size()); // number of elements + s.PutU4(uint32_t(v.size())); // number of elements s.PutU4(0); // no encoding (1 would be zip-compressed) - s.PutU4(v.size() * 4); // data size + s.PutU4(uint32_t(v.size()) * 4); // data size for (auto it = v.begin(); it != v.end(); ++it) { s.PutI4(*it); } node.EndProperties(s, 1); node.End(s, false); diff --git a/code/FBXExportProperty.cpp b/code/FBXExportProperty.cpp index 1beaa4d27..975e9a09a 100644 --- a/code/FBXExportProperty.cpp +++ b/code/FBXExportProperty.cpp @@ -127,8 +127,8 @@ FBX::Property::Property(const aiMatrix4x4& vm) : type('d'), data(8*16) { double* d = reinterpret_cast(data.data()); - for (size_t c = 0; c < 4; ++c) { - for (size_t r = 0; r < 4; ++r) { + for (unsigned int c = 0; c < 4; ++c) { + for (unsigned int r = 0; r < 4; ++r) { d[4*c+r] = vm[r][c]; } } @@ -164,15 +164,15 @@ void FBX::Property::Dump(Assimp::StreamWriterLE &s) case 'L': s.PutI8(*(reinterpret_cast(data.data()))); return; case 'S': case 'R': - s.PutU4(data.size()); + s.PutU4(uint32_t(data.size())); for (size_t i = 0; i < data.size(); ++i) { s.PutU1(data[i]); } return; case 'i': N = data.size() / 4; - s.PutU4(N); // number of elements + s.PutU4(uint32_t(N)); // number of elements s.PutU4(0); // no encoding (1 would be zip-compressed) // TODO: compress if large? - s.PutU4(data.size()); // data size + s.PutU4(uint32_t(data.size())); // data size d = data.data(); for (size_t i = 0; i < N; ++i) { s.PutI4((reinterpret_cast(d))[i]); @@ -180,10 +180,10 @@ void FBX::Property::Dump(Assimp::StreamWriterLE &s) return; case 'd': N = data.size() / 8; - s.PutU4(N); // number of elements + s.PutU4(uint32_t(N)); // number of elements s.PutU4(0); // no encoding (1 would be zip-compressed) // TODO: compress if large? - s.PutU4(data.size()); // data size + s.PutU4(uint32_t(data.size())); // data size d = data.data(); for (size_t i = 0; i < N; ++i) { s.PutF8((reinterpret_cast(d))[i]); diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index a2e6024ed..9ba5c0333 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -460,7 +460,7 @@ size_t count_images(const aiScene* scene) { ){ const aiTextureType textype = static_cast(tt); const size_t texcount = mat->GetTextureCount(textype); - for (size_t j = 0; j < texcount; ++j) { + for (unsigned int j = 0; j < texcount; ++j) { mat->GetTexture(textype, j, &texpath); images.insert(std::string(texpath.C_Str())); } @@ -593,7 +593,7 @@ void FBXExporter::WriteDefinitions () // Model / FbxNode // <~~ node heirarchy - count = count_nodes(mScene->mRootNode) - 1; // (not counting root node) + count = int32_t(count_nodes(mScene->mRootNode)) - 1; // (not counting root node) if (count) { n = FBX::Node("ObjectType", Property("Model")); n.AddChild("Count", count); @@ -763,7 +763,7 @@ void FBXExporter::WriteDefinitions () // Video / FbxVideo // one for each image file. - count = count_images(mScene); + count = int32_t(count_images(mScene)); if (count) { n = FBX::Node("ObjectType", Property("Video")); n.AddChild("Count", count); @@ -792,7 +792,7 @@ void FBXExporter::WriteDefinitions () // Texture / FbxFileTexture // <~~ aiTexture - count = count_textures(mScene); + count = int32_t(count_textures(mScene)); if (count) { n = FBX::Node("ObjectType", Property("Texture")); n.AddChild("Count", count); @@ -848,7 +848,7 @@ void FBXExporter::WriteDefinitions () } // Deformer - count = count_deformers(mScene); + count = int32_t(count_deformers(mScene)); if (count) { n = FBX::Node("ObjectType", Property("Deformer")); n.AddChild("Count", count); @@ -943,7 +943,7 @@ void FBXExporter::WriteObjects () std::vector vertex_indices; // map of vertex value to its index in the data vector std::map index_by_vertex_value; - size_t index = 0; + int32_t index = 0; for (size_t vi = 0; vi < m->mNumVertices; ++vi) { aiVector3D vtx = m->mVertices[vi]; auto elem = index_by_vertex_value.find(vtx); @@ -955,7 +955,7 @@ void FBXExporter::WriteObjects () flattened_vertices.push_back(vtx[2]); ++index; } else { - vertex_indices.push_back(elem->second); + vertex_indices.push_back(int32_t(elem->second)); } } FBX::Node::WritePropertyNode( @@ -1052,7 +1052,7 @@ void FBXExporter::WriteObjects () std::vector uv_data; std::vector uv_indices; std::map index_by_uv; - size_t index = 0; + int32_t index = 0; for (size_t fi = 0; fi < m->mNumFaces; ++fi) { const aiFace &f = m->mFaces[fi]; for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) { @@ -1062,7 +1062,7 @@ void FBXExporter::WriteObjects () if (elem == index_by_uv.end()) { index_by_uv[uv] = index; uv_indices.push_back(index); - for (size_t x = 0; x < m->mNumUVComponents[uvi]; ++x) { + for (unsigned int x = 0; x < m->mNumUVComponents[uvi]; ++x) { uv_data.push_back(uv[x]); } ++index; @@ -1208,13 +1208,13 @@ void FBXExporter::WriteObjects () // and usualy are completely ignored when loading. // One notable exception is the "Opacity" property, // which Blender uses as (1.0 - alpha). - c.r = 0; c.g = 0; c.b = 0; + c.r = 0.0f; c.g = 0.0f; c.b = 0.0f; m->Get(AI_MATKEY_COLOR_EMISSIVE, c); p.AddP70vector("Emissive", c.r, c.g, c.b); - c.r = 0.2; c.g = 0.2; c.b = 0.2; + c.r = 0.2f; c.g = 0.2f; c.b = 0.2f; m->Get(AI_MATKEY_COLOR_AMBIENT, c); p.AddP70vector("Ambient", c.r, c.g, c.b); - c.r = 0.8; c.g = 0.8; c.b = 0.8; + c.r = 0.8f; c.g = 0.8f; c.b = 0.8f; m->Get(AI_MATKEY_COLOR_DIFFUSE, c); p.AddP70vector("Diffuse", c.r, c.g, c.b); // The FBX SDK determines "Opacity" from transparency colour (RGB) @@ -1223,29 +1223,29 @@ void FBXExporter::WriteObjects () // so we should take it from AI_MATKEY_OPACITY if possible. // It might make more sense to use TransparencyFactor, // but Blender actually loads "Opacity" correctly, so let's use it. - f = 1.0; + f = 1.0f; if (m->Get(AI_MATKEY_COLOR_TRANSPARENT, c) == aiReturn_SUCCESS) { - f = 1.0 - ((c.r + c.g + c.b) / 3); + f = 1.0f - ((c.r + c.g + c.b) / 3.0f); } m->Get(AI_MATKEY_OPACITY, f); p.AddP70double("Opacity", f); if (phong) { // specular color is multiplied by shininess_strength - c.r = 0.2; c.g = 0.2; c.b = 0.2; + c.r = 0.2f; c.g = 0.2f; c.b = 0.2f; m->Get(AI_MATKEY_COLOR_SPECULAR, c); - f = 1.0; + f = 1.0f; m->Get(AI_MATKEY_SHININESS_STRENGTH, f); p.AddP70vector("Specular", f*c.r, f*c.g, f*c.b); - f = 20.0; + f = 20.0f; m->Get(AI_MATKEY_SHININESS, f); p.AddP70double("Shininess", f); // Legacy "Reflectivity" is F*F*((R+G+B)/3), // where F is the proportion of light reflected (AKA reflectivity), // and RGB is the reflective colour of the material. // No idea why, but we might as well set it the same way. - f = 0.0; + f = 0.0f; m->Get(AI_MATKEY_REFLECTIVITY, f); - c.r = 1.0, c.g = 1.0, c.b = 1.0; + c.r = 1.0f, c.g = 1.0f, c.b = 1.0f; m->Get(AI_MATKEY_COLOR_REFLECTIVE, c); p.AddP70double("Reflectivity", f*f*((c.r+c.g+c.b)/3.0)); } @@ -1269,7 +1269,7 @@ void FBXExporter::WriteObjects () const aiTextureType textype = static_cast(tt); const size_t texcount = mat->GetTextureCount(textype); for (size_t j = 0; j < texcount; ++j) { - mat->GetTexture(textype, j, &texpath); + mat->GetTexture(textype, (unsigned int)j, &texpath); const std::string texstring = texpath.C_Str(); auto elem = uid_by_image.find(texstring); if (elem == uid_by_image.end()) { @@ -1591,7 +1591,7 @@ void FBXExporter::WriteObjects () std::vector vertex_indices; // map of vertex value to its index in the data vector std::map index_by_vertex_value; - size_t index = 0; + int32_t index = 0; for (size_t vi = 0; vi < m->mNumVertices; ++vi) { aiVector3D vtx = m->mVertices[vi]; auto elem = index_by_vertex_value.find(vtx); @@ -1600,7 +1600,7 @@ void FBXExporter::WriteObjects () index_by_vertex_value[vtx] = index; ++index; } else { - vertex_indices.push_back(elem->second); + vertex_indices.push_back(int32_t(elem->second)); } } @@ -1616,7 +1616,7 @@ void FBXExporter::WriteObjects () // as it can be instanced to many nodes. // All we can do is assume no instancing, // and take the first node we find that contains the mesh. - aiNode* mesh_node = get_node_for_mesh(mi, mScene->mRootNode); + aiNode* mesh_node = get_node_for_mesh((unsigned int)mi, mScene->mRootNode); aiMatrix4x4 mesh_xform = get_world_transform(mesh_node, mScene); // now make a subdeformer for each bone in the skeleton @@ -1682,7 +1682,7 @@ void FBXExporter::WriteObjects () // this should be the same as the bone's mOffsetMatrix. // if it's not the same, the skeleton isn't in the bind pose. - const float epsilon = 1e-5; // some error is to be expected + const float epsilon = 1e-5f; // some error is to be expected bool bone_xform_okay = true; if (b && ! tr.Equal(b->mOffsetMatrix, epsilon)) { not_in_bind_pose.insert(b); @@ -2002,7 +2002,7 @@ void FBXExporter::WriteModelNodes( transform_chain.emplace_back(elem->first, t); break; case 'r': // rotation - r *= DEG; + r *= float(DEG); transform_chain.emplace_back(elem->first, r); break; case 's': // scale diff --git a/code/XFileParser.cpp b/code/XFileParser.cpp index bda59ba59..4dd2c990b 100644 --- a/code/XFileParser.cpp +++ b/code/XFileParser.cpp @@ -1076,8 +1076,8 @@ std::string XFileParser::GetNextToken() { return s; } len = ReadBinDWord(); - const int bounds( mEnd - mP ); - const int iLen( len ); + const int bounds = int( mEnd - mP ); + const int iLen = int( len ); if ( iLen < 0 ) { return s; } diff --git a/include/assimp/StreamWriter.h b/include/assimp/StreamWriter.h index e955a7255..6f492df90 100644 --- a/include/assimp/StreamWriter.h +++ b/include/assimp/StreamWriter.h @@ -104,7 +104,7 @@ public: // --------------------------------------------------------------------- ~StreamWriter() { - stream->Write(&buffer[0], 1, buffer.size()); + stream->Write(buffer.data(), 1, buffer.size()); stream->Flush(); } @@ -114,7 +114,7 @@ public: /** Flush the contents of the internal buffer, and the output IOStream */ void Flush() { - stream->Write(&buffer[0], 1, buffer.size()); + stream->Write(buffer.data(), 1, buffer.size()); stream->Flush(); buffer.clear(); cursor = 0; From ef12eb84bbfefc4b999876c4d8ac9a3ec7b7f419 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 20 Mar 2018 10:09:47 +0100 Subject: [PATCH 091/278] 3MF: add metadata import. --- code/D3MFImporter.cpp | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index 3fffa5aeb..9153b1790 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -102,6 +102,8 @@ public: // } else if ( nodeName == D3MF::XmlTag::basematerials ) { ReadBaseMaterials(); + } else if ( nodeName == D3MF::XmlTag::meta ) { + ReadMetadata(); } } @@ -109,6 +111,15 @@ public: scene->mRootNode->mName.Set( "3MF" ); } + if ( !mMetaData.empty() ) { + const size_t numMeta( mMetaData.size() ); + scene->mMetaData = aiMetadata::Alloc( numMeta ); + for ( size_t i = 0; i < numMeta; ++i ) { + aiString val( mMetaData[ i ].value ); + scene->mMetaData->Add( mMetaData[ i ].name, val ); + } + } + scene->mNumMeshes = static_cast( mMeshes.size()); scene->mMeshes = new aiMesh*[scene->mNumMeshes](); @@ -180,6 +191,21 @@ private: return mesh; } + void ReadMetadata() { + const std::string name = xmlReader->getAttributeValue( D3MF::XmlTag::meta_name.c_str() ); + xmlReader->read(); + const std::string value = xmlReader->getNodeData(); + + if ( name.empty() ) { + return; + } + + MetaEntry entry; + entry.name = name; + entry.value = value; + mMetaData.push_back( entry ); + } + void ImportVertices(aiMesh* mesh) { std::vector vertices; while(ReadToEndElement(D3MF::XmlTag::vertices)) { @@ -371,8 +397,12 @@ private: return false; } - private: + struct MetaEntry { + std::string name; + std::string value; + }; + std::vector mMetaData; std::vector mMeshes; MatArray mMatArray; unsigned int mActiveMatGroup; From b66bee8d79dc388aba3cc5e3150a40e1e313ecf0 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 20 Mar 2018 14:09:07 +0100 Subject: [PATCH 092/278] Export: Copy metadata to be able to export it properly. --- code/SceneCombiner.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/code/SceneCombiner.cpp b/code/SceneCombiner.cpp index 8647bd1ba..f67ef547c 100644 --- a/code/SceneCombiner.cpp +++ b/code/SceneCombiner.cpp @@ -55,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include #include "time.h" #include @@ -1001,7 +1002,12 @@ void SceneCombiner::CopyScene(aiScene** _dest,const aiScene* src,bool allocate) *_dest = new aiScene(); } aiScene* dest = *_dest; - ai_assert(dest); + ai_assert(nullptr != dest); + + // copy metadata + if ( nullptr != src->mMetaData ) { + dest->mMetaData = new aiMetadata( *src->mMetaData ); + } // copy animations dest->mNumAnimations = src->mNumAnimations; From 3bcef7ed8fe9a196574d0a7fd82a5209a8ae4486 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 20 Mar 2018 14:09:52 +0100 Subject: [PATCH 093/278] Metadata: add test for copying metadata via copy constructor. --- test/unit/utMetadata.cpp | 71 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/test/unit/utMetadata.cpp b/test/unit/utMetadata.cpp index 7fda143b7..42f632bce 100644 --- a/test/unit/utMetadata.cpp +++ b/test/unit/utMetadata.cpp @@ -181,3 +181,74 @@ TEST_F( utMetadata, get_set_aiVector3D_Test ) { EXPECT_TRUE( success ); } +TEST_F( utMetadata, copy_test ) { + m_data = aiMetadata::Alloc( AI_META_MAX ); + bool bv = true; + m_data->Set( 0, "bool", bv ); + int32_t i32v = -10; + m_data->Set( 1, "int32", i32v ); + uint64_t ui64v = static_cast( 10 ); + m_data->Set( 2, "uint64", ui64v ); + float fv = 1.0f; + m_data->Set( 3, "float", fv ); + double dv = 2.0; + m_data->Set( 4, "double", dv ); + const aiString strVal( std::string( "test" ) ); + m_data->Set( 5, "aiString", strVal ); + aiVector3D vecVal( 1, 2, 3 ); + m_data->Set( 6, "aiVector3D", vecVal ); + + aiMetadata copy( *m_data ); + EXPECT_EQ( 7, copy.mNumProperties ); + + // bool test + { + bool v; + EXPECT_TRUE( copy.Get( "bool", v ) ); + EXPECT_EQ( bv, v ); + } + + // int32_t test + { + int32_t v; + bool ok = copy.Get( "int32", v ); + EXPECT_TRUE( ok ); + EXPECT_EQ( i32v, v ); + } + + // uint64_t test + { + uint64_t v; + bool ok = copy.Get( "uint64", v ); + EXPECT_TRUE( ok ); + EXPECT_EQ( ui64v, v ); + } + + // float test + { + float v; + EXPECT_TRUE( copy.Get( "float", v ) ); + EXPECT_EQ( fv, v ); + } + + // double test + { + double v; + EXPECT_TRUE( copy.Get( "double", v ) ); + EXPECT_EQ( dv, v ); + } + + // bool test + { + aiString v; + EXPECT_TRUE( copy.Get( "aiString", v ) ); + EXPECT_EQ( strVal, v ); + } + + // bool test + { + aiVector3D v; + EXPECT_TRUE( copy.Get( "aiVector3D", v ) ); + EXPECT_EQ( vecVal, v ); + } +} From 317f3e2a59059fe689e9182cd922ba185c1a48b6 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 20 Mar 2018 14:10:08 +0100 Subject: [PATCH 094/278] 3MF: Export metadata. --- code/D3MFExporter.cpp | 26 +++++++++++ code/D3MFExporter.h | 1 + code/D3MFImporter.cpp | 9 ++-- code/Exporter.cpp | 3 +- include/assimp/metadata.h | 98 ++++++++++++++++++++++++++++++++------- 5 files changed, 116 insertions(+), 21 deletions(-) diff --git a/code/D3MFExporter.cpp b/code/D3MFExporter.cpp index b89e81ce6..950793f44 100644 --- a/code/D3MFExporter.cpp +++ b/code/D3MFExporter.cpp @@ -117,6 +117,7 @@ bool D3MFExporter::exportArchive( const char *file ) { if ( nullptr == m_zipArchive ) { return false; } + ok |= exportContentTypes(); ok |= export3DModel(); ok |= exportRelations(); @@ -181,6 +182,8 @@ bool D3MFExporter::export3DModel() { mModelOutput << "<" << XmlTag::resources << ">"; mModelOutput << std::endl; + writeMetaData(); + writeBaseMaterials(); writeObjects(); @@ -209,6 +212,29 @@ void D3MFExporter::writeHeader() { mModelOutput << std::endl; } +void D3MFExporter::writeMetaData() { + if ( nullptr == mScene->mMetaData ) { + return; + } + + const unsigned int numMetaEntries( mScene->mMetaData->mNumProperties ); + if ( 0 == numMetaEntries ) { + return; + } + + const aiString *key; + const aiMetadataEntry *entry(nullptr); + for ( size_t i = 0; i < numMetaEntries; ++i ) { + mScene->mMetaData->Get( i, key, entry ); + std::string k( key->C_Str() ); + aiString value; + mScene->mMetaData->Get( k, value ); + mModelOutput << "<" << XmlTag::meta << " " << XmlTag::meta_name << "=\"" << key->C_Str() << "\">"; + mModelOutput << value.C_Str(); + mModelOutput << "" << std::endl; + } +} + void D3MFExporter::writeBaseMaterials() { mModelOutput << "\n"; for ( size_t i = 0; i < mScene->mNumMaterials; ++i ) { diff --git a/code/D3MFExporter.h b/code/D3MFExporter.h index b553e0ab5..110862b99 100644 --- a/code/D3MFExporter.h +++ b/code/D3MFExporter.h @@ -76,6 +76,7 @@ public: protected: void writeHeader(); + void writeMetaData(); void writeBaseMaterials(); void writeObjects(); void writeMesh( aiMesh *mesh ); diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index 9153b1790..d9f498ebf 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -111,28 +111,31 @@ public: scene->mRootNode->mName.Set( "3MF" ); } + // import the metadata if ( !mMetaData.empty() ) { const size_t numMeta( mMetaData.size() ); scene->mMetaData = aiMetadata::Alloc( numMeta ); for ( size_t i = 0; i < numMeta; ++i ) { aiString val( mMetaData[ i ].value ); - scene->mMetaData->Add( mMetaData[ i ].name, val ); + scene->mMetaData->Set( i, mMetaData[ i ].name, val ); } } + // import the meshes scene->mNumMeshes = static_cast( mMeshes.size()); scene->mMeshes = new aiMesh*[scene->mNumMeshes](); - std::copy( mMeshes.begin(), mMeshes.end(), scene->mMeshes); + // import the materials scene->mNumMaterials = static_cast( mMatArray.size() ); if ( 0 != scene->mNumMaterials ) { scene->mMaterials = new aiMaterial*[ scene->mNumMaterials ]; std::copy( mMatArray.begin(), mMatArray.end(), scene->mMaterials ); } + + // create the scenegraph scene->mRootNode->mNumChildren = static_cast(children.size()); scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren](); - std::copy(children.begin(), children.end(), scene->mRootNode->mChildren); } diff --git a/code/Exporter.cpp b/code/Exporter.cpp index 4951c70ef..49523e658 100644 --- a/code/Exporter.cpp +++ b/code/Exporter.cpp @@ -308,7 +308,8 @@ bool IsVerboseFormat(const aiScene* pScene) { } // ------------------------------------------------------------------------------------------------ -aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing, const ExportProperties* pProperties) { +aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const char* pPath, + unsigned int pPreprocessing, const ExportProperties* pProperties) { ASSIMP_BEGIN_EXCEPTION_REGION(); // when they create scenes from scratch, users will likely create them not in verbose diff --git a/include/assimp/metadata.h b/include/assimp/metadata.h index 2dba61abc..70a604de9 100644 --- a/include/assimp/metadata.h +++ b/include/assimp/metadata.h @@ -67,6 +67,7 @@ typedef enum aiMetadataType { AI_DOUBLE = 4, AI_AISTRING = 5, AI_AIVECTOR3D = 6, + AI_META_MAX = 7, #ifndef SWIG FORCE_32BIT = INT_MAX @@ -130,42 +131,103 @@ struct aiMetadata { */ aiMetadata() : mNumProperties(0) - , mKeys(NULL) - , mValues(NULL) { + , mKeys(nullptr) + , mValues(nullptr) { // empty } + aiMetadata( const aiMetadata &rhs ) + : mNumProperties( rhs.mNumProperties ) + , mKeys( nullptr ) + , mValues( nullptr ) { + mKeys = new aiString[ mNumProperties ]; + for ( unsigned int i = 0; i < mNumProperties; ++i ) { + mKeys[ i ] = rhs.mKeys[ i ]; + } + mValues = new aiMetadataEntry[ mNumProperties ]; + for ( unsigned int i = 0; i < mNumProperties; ++i ) { + mValues[ i ].mType = rhs.mValues[ i ].mType; + switch ( rhs.mValues[ i ].mType ) { + case AI_BOOL: + mValues[ i ].mData = new bool( rhs.mValues[i].mData ); + break; + case AI_INT32: { + int32_t v; + ::memcpy( &v, rhs.mValues[ i ].mData, sizeof( int32_t ) ); + mValues[ i ].mData = new int32_t( v ); + } + break; + case AI_UINT64: { + uint64_t v; + ::memcpy( &v, rhs.mValues[ i ].mData, sizeof( uint64_t ) ); + mValues[ i ].mData = new uint64_t( v ); + } + break; + case AI_FLOAT: { + float v; + ::memcpy( &v, rhs.mValues[ i ].mData, sizeof( float ) ); + mValues[ i ].mData = new float( v ); + } + break; + case AI_DOUBLE: { + double v; + ::memcpy( &v, rhs.mValues[ i ].mData, sizeof( double ) ); + mValues[ i ].mData = new double( v ); + } + break; + case AI_AISTRING: { + aiString v; + rhs.Get( mKeys[ i ], v ); + mValues[ i ].mData = new aiString( v ); + } + break; + case AI_AIVECTOR3D: { + aiVector3D v; + rhs.Get( mKeys[ i ], v ); + mValues[ i ].mData = new aiVector3D( v ); + } + break; +#ifndef SWIG + case FORCE_32BIT: +#endif + default: + break; + } + + } + } + /** * @brief The destructor. */ ~aiMetadata() { delete [] mKeys; - mKeys = NULL; + mKeys = nullptr; if (mValues) { // Delete each metadata entry for (unsigned i=0; i(data); + delete static_cast< bool* >( data ); break; case AI_INT32: - delete static_cast(data); + delete static_cast< int32_t* >( data ); break; case AI_UINT64: - delete static_cast(data); + delete static_cast< uint64_t* >( data ); break; case AI_FLOAT: - delete static_cast(data); + delete static_cast< float* >( data ); break; case AI_DOUBLE: - delete static_cast(data); + delete static_cast< double* >( data ); break; case AI_AISTRING: - delete static_cast(data); + delete static_cast< aiString* >( data ); break; case AI_AIVECTOR3D: - delete static_cast(data); + delete static_cast< aiVector3D* >( data ); break; #ifndef SWIG case FORCE_32BIT: @@ -177,7 +239,7 @@ struct aiMetadata { // Delete the metadata array delete [] mValues; - mValues = NULL; + mValues = nullptr; } } @@ -208,8 +270,8 @@ struct aiMetadata { } template - inline void Add(const std::string& key, const T& value) - { + inline + void Add(const std::string& key, const T& value) { aiString* new_keys = new aiString[mNumProperties + 1]; aiMetadataEntry* new_values = new aiMetadataEntry[mNumProperties + 1]; @@ -256,7 +318,7 @@ struct aiMetadata { template inline - bool Get( unsigned index, T& value ) { + bool Get( unsigned index, T& value ) const { // In range assertion if ( index >= mNumProperties ) { return false; @@ -277,7 +339,7 @@ struct aiMetadata { template inline - bool Get( const aiString& key, T& value ) { + bool Get( const aiString& key, T& value ) const { // Search for the given key for ( unsigned int i = 0; i < mNumProperties; ++i ) { if ( mKeys[ i ] == key ) { @@ -288,7 +350,8 @@ struct aiMetadata { } template - inline bool Get( const std::string& key, T& value ) { + inline + bool Get( const std::string& key, T& value ) const { return Get(aiString(key), value); } @@ -297,7 +360,8 @@ struct aiMetadata { /// \param [out] pKey - pointer to the key value. /// \param [out] pEntry - pointer to the entry: type and value. /// \return false - if pIndex is out of range, else - true. - inline bool Get(size_t index, const aiString*& key, const aiMetadataEntry*& entry) { + inline + bool Get(size_t index, const aiString*& key, const aiMetadataEntry*& entry) const { if ( index >= mNumProperties ) { return false; } From e36f78482cc561d04a4cf21b457d5b5b4bbc0c03 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 20 Mar 2018 14:53:57 +0100 Subject: [PATCH 095/278] https://github.com/assimp/assimp/issues/1796: return correct value on detach logger. --- code/DefaultLogger.cpp | 124 +++++++++++++++++++---------------------- 1 file changed, 56 insertions(+), 68 deletions(-) diff --git a/code/DefaultLogger.cpp b/code/DefaultLogger.cpp index ad101174c..2871a4131 100644 --- a/code/DefaultLogger.cpp +++ b/code/DefaultLogger.cpp @@ -45,7 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Implementation of DefaultLogger (and Logger) */ - // Default log streams #include "Win32DebugLogStream.h" #include "StdOStreamLogStream.h" @@ -62,8 +61,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_SINGLETHREADED # include # include - -std::mutex loggerMutex; + std::mutex loggerMutex; #endif namespace Assimp { @@ -76,22 +74,19 @@ static const unsigned int SeverityAll = Logger::Info | Logger::Err | Logger::War // ---------------------------------------------------------------------------------- // Represents a log-stream + its error severity -struct LogStreamInfo -{ - unsigned int m_uiErrorSeverity; - LogStream *m_pStream; +struct LogStreamInfo { + unsigned int m_uiErrorSeverity; + LogStream *m_pStream; // Constructor LogStreamInfo( unsigned int uiErrorSev, LogStream *pStream ) : m_uiErrorSeverity( uiErrorSev ), - m_pStream( pStream ) - { + m_pStream( pStream ) { // empty } // Destructor - ~LogStreamInfo() - { + ~LogStreamInfo() { delete m_pStream; } }; @@ -109,7 +104,7 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams, #ifdef WIN32 return new Win32DebugLogStream(); #else - return NULL; + return nullptr; #endif // Platform-independent default streams @@ -118,7 +113,7 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams, case aiDefaultLogStream_STDOUT: return new StdOStreamLogStream(std::cout); case aiDefaultLogStream_FILE: - return (name && *name ? new FileLogStream(name,io) : NULL); + return (name && *name ? new FileLogStream(name,io) : nullptr ); default: // We don't know this default log stream, so raise an assertion ai_assert(false); @@ -134,34 +129,38 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams, Logger *DefaultLogger::create(const char* name /*= "AssimpLog.txt"*/, LogSeverity severity /*= NORMAL*/, unsigned int defStreams /*= aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE*/, - IOSystem* io /*= NULL*/) -{ + IOSystem* io /*= NULL*/) { // enter the mutex here to avoid concurrency problems #ifndef ASSIMP_BUILD_SINGLETHREADED std::lock_guard lock(loggerMutex); #endif - if (m_pLogger && !isNullLogger() ) + if ( m_pLogger && !isNullLogger() ) { delete m_pLogger; + } m_pLogger = new DefaultLogger( severity ); // Attach default log streams // Stream the log to the MSVC debugger? - if (defStreams & aiDefaultLogStream_DEBUGGER) - m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_DEBUGGER)); + if ( defStreams & aiDefaultLogStream_DEBUGGER ) { + m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_DEBUGGER ) ); + } // Stream the log to COUT? - if (defStreams & aiDefaultLogStream_STDOUT) - m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDOUT)); + if ( defStreams & aiDefaultLogStream_STDOUT ) { + m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_STDOUT ) ); + } // Stream the log to CERR? - if (defStreams & aiDefaultLogStream_STDERR) - m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDERR)); + if ( defStreams & aiDefaultLogStream_STDERR ) { + m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_STDERR ) ); + } // Stream the log to a file - if (defStreams & aiDefaultLogStream_FILE && name && *name) - m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_FILE,name,io)); + if ( defStreams & aiDefaultLogStream_FILE && name && *name ) { + m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_FILE, name, io ) ); + } return m_pLogger; } @@ -200,7 +199,6 @@ void Logger::warn(const char* message) { // ---------------------------------------------------------------------------------- void Logger::error(const char* message) { - // SECURITY FIX: see above if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) { return; @@ -209,23 +207,24 @@ void Logger::error(const char* message) { } // ---------------------------------------------------------------------------------- -void DefaultLogger::set( Logger *logger ) -{ +void DefaultLogger::set( Logger *logger ) { // enter the mutex here to avoid concurrency problems #ifndef ASSIMP_BUILD_SINGLETHREADED std::lock_guard lock(loggerMutex); #endif - if (!logger)logger = &s_pNullLogger; - if (m_pLogger && !isNullLogger() ) + if ( nullptr == logger ) { + logger = &s_pNullLogger; + } + if ( nullptr != m_pLogger && !isNullLogger() ) { delete m_pLogger; + } DefaultLogger::m_pLogger = logger; } // ---------------------------------------------------------------------------------- -bool DefaultLogger::isNullLogger() -{ +bool DefaultLogger::isNullLogger() { return m_pLogger == &s_pNullLogger; } @@ -236,8 +235,7 @@ Logger *DefaultLogger::get() { // ---------------------------------------------------------------------------------- // Kills the only instance -void DefaultLogger::kill() -{ +void DefaultLogger::kill() { // enter the mutex here to avoid concurrency problems #ifndef ASSIMP_BUILD_SINGLETHREADED std::lock_guard lock(loggerMutex); @@ -252,10 +250,10 @@ void DefaultLogger::kill() // ---------------------------------------------------------------------------------- // Debug message -void DefaultLogger::OnDebug( const char* message ) -{ - if ( m_Severity == Logger::NORMAL ) - return; +void DefaultLogger::OnDebug( const char* message ) { + if ( m_Severity == Logger::NORMAL ) { + return; + } static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; char msg[Size]; @@ -266,8 +264,7 @@ void DefaultLogger::OnDebug( const char* message ) // ---------------------------------------------------------------------------------- // Logs an info -void DefaultLogger::OnInfo( const char* message ) -{ +void DefaultLogger::OnInfo( const char* message ){ static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; char msg[Size]; ai_snprintf(msg, Size, "Info, T%u: %s", GetThreadID(), message ); @@ -277,8 +274,7 @@ void DefaultLogger::OnInfo( const char* message ) // ---------------------------------------------------------------------------------- // Logs a warning -void DefaultLogger::OnWarn( const char* message ) -{ +void DefaultLogger::OnWarn( const char* message ) { static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; char msg[Size]; ai_snprintf(msg, Size, "Warn, T%u: %s", GetThreadID(), message ); @@ -288,8 +284,7 @@ void DefaultLogger::OnWarn( const char* message ) // ---------------------------------------------------------------------------------- // Logs an error -void DefaultLogger::OnError( const char* message ) -{ +void DefaultLogger::OnError( const char* message ) { static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; char msg[ Size ]; ai_snprintf(msg, Size, "Error, T%u: %s", GetThreadID(), message ); @@ -299,10 +294,10 @@ void DefaultLogger::OnError( const char* message ) // ---------------------------------------------------------------------------------- // Will attach a new stream -bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity ) -{ - if (!pStream) +bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity ) { + if ( nullptr == pStream ) { return false; + } if (0 == severity) { severity = Logger::Info | Logger::Err | Logger::Warn | Logger::Debugging; @@ -312,8 +307,7 @@ bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity ) it != m_StreamArray.end(); ++it ) { - if ( (*it)->m_pStream == pStream ) - { + if ( (*it)->m_pStream == pStream ) { (*it)->m_uiErrorSeverity |= severity; return true; } @@ -326,34 +320,31 @@ bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity ) // ---------------------------------------------------------------------------------- // Detach a stream -bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity ) -{ - if (!pStream) +bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity ) { + if ( nullptr == pStream ) { return false; + } if (0 == severity) { severity = SeverityAll; } - for ( StreamIt it = m_StreamArray.begin(); - it != m_StreamArray.end(); - ++it ) - { - if ( (*it)->m_pStream == pStream ) - { + bool res( false ); + for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) { + if ( (*it)->m_pStream == pStream ) { (*it)->m_uiErrorSeverity &= ~severity; - if ( (*it)->m_uiErrorSeverity == 0 ) - { + if ( (*it)->m_uiErrorSeverity == 0 ) { // don't delete the underlying stream 'cause the caller gains ownership again - (**it).m_pStream = NULL; + (**it).m_pStream = nullptr; delete *it; m_StreamArray.erase( it ); + res = true; break; } return true; } } - return false; + return res; } // ---------------------------------------------------------------------------------- @@ -361,15 +352,13 @@ bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity ) DefaultLogger::DefaultLogger(LogSeverity severity) : Logger ( severity ) , noRepeatMsg (false) - , lastLen( 0 ) -{ + , lastLen( 0 ) { lastMsg[0] = '\0'; } // ---------------------------------------------------------------------------------- // Destructor -DefaultLogger::~DefaultLogger() -{ +DefaultLogger::~DefaultLogger() { for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) { // also frees the underlying stream, we are its owner. delete *it; @@ -378,9 +367,8 @@ DefaultLogger::~DefaultLogger() // ---------------------------------------------------------------------------------- // Writes message to stream -void DefaultLogger::WriteToStreams(const char *message, ErrorSeverity ErrorSev ) -{ - ai_assert(NULL != message); +void DefaultLogger::WriteToStreams(const char *message, ErrorSeverity ErrorSev ) { + ai_assert(nullptr != message); // Check whether this is a repeated message if (! ::strncmp( message,lastMsg, lastLen-1)) From 5814e6f9f066f5f5d24b3796639675a38ba43dfa Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 20 Mar 2018 18:43:54 +0100 Subject: [PATCH 096/278] Optimize some std::string usages. --- code/3DSConverter.cpp | 2 +- code/AMFImporter_Postprocess.cpp | 9 +++++---- code/ASEParser.cpp | 26 +++++++++++++------------- code/BVHLoader.cpp | 27 ++++++++++++++------------- code/BaseImporter.cpp | 3 ++- code/ColladaExporter.cpp | 14 +++++++++----- code/ColladaLoader.cpp | 12 ++++++++---- code/D3MFExporter.cpp | 6 +++--- code/D3MFImporter.cpp | 3 ++- code/D3MFOpcPackage.cpp | 4 ++-- code/DXFHelper.h | 1 - code/FBXConverter.cpp | 5 ++--- code/Importer.cpp | 2 +- code/SceneCombiner.cpp | 18 ++++++++++-------- include/assimp/DefaultLogger.hpp | 4 ---- 15 files changed, 72 insertions(+), 64 deletions(-) diff --git a/code/3DSConverter.cpp b/code/3DSConverter.cpp index cbc6d31d2..081da1bcf 100644 --- a/code/3DSConverter.cpp +++ b/code/3DSConverter.cpp @@ -72,7 +72,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() unsigned int idx( NotSet ); for (unsigned int i = 0; i < mScene->mMaterials.size();++i) { - std::string s = mScene->mMaterials[i].mName; + std::string &s = mScene->mMaterials[i].mName; for ( std::string::iterator it = s.begin(); it != s.end(); ++it ) { *it = static_cast< char >( ::tolower( *it ) ); } diff --git a/code/AMFImporter_Postprocess.cpp b/code/AMFImporter_Postprocess.cpp index f048e1178..192544fcb 100644 --- a/code/AMFImporter_Postprocess.cpp +++ b/code/AMFImporter_Postprocess.cpp @@ -156,10 +156,11 @@ size_t AMFImporter::PostprocessHelper_GetTextureID_Or_Create(const std::string& TextureConverted_Index = 0; for(const SPP_Texture& tex_convd: mTexture_Converted) { - if(tex_convd.ID == TextureConverted_ID) - return TextureConverted_Index; - else - TextureConverted_Index++; + if ( tex_convd.ID == TextureConverted_ID ) { + return TextureConverted_Index; + } else { + ++TextureConverted_Index; + } } // diff --git a/code/ASEParser.cpp b/code/ASEParser.cpp index 59af24a10..b953f8d96 100644 --- a/code/ASEParser.cpp +++ b/code/ASEParser.cpp @@ -267,7 +267,9 @@ void Parser::Parse() // at the file extension (ASE, ASK, ASC) // ************************************************************* - if (fmt)iFileFormat = fmt; + if ( fmt ) { + iFileFormat = fmt; + } continue; } // main scene information @@ -427,28 +429,25 @@ void Parser::ParseLV1SoftSkinBlock() // Reserve enough storage vert.mBoneWeights.reserve(numWeights); - for (unsigned int w = 0; w < numWeights;++w) - { - std::string bone; + std::string bone; + for (unsigned int w = 0; w < numWeights;++w) { + bone.clear(); ParseString(bone,"*MESH_SOFTSKINVERTS.Bone"); // Find the bone in the mesh's list std::pair me; me.first = -1; - for (unsigned int n = 0; n < curMesh->mBones.size();++n) - { - if (curMesh->mBones[n].mName == bone) - { + for (unsigned int n = 0; n < curMesh->mBones.size();++n) { + if (curMesh->mBones[n].mName == bone) { me.first = n; break; } } - if (-1 == me.first) - { + if (-1 == me.first) { // We don't have this bone yet, so add it to the list - me.first = (int)curMesh->mBones.size(); - curMesh->mBones.push_back(ASE::Bone(bone)); + me.first = static_cast( curMesh->mBones.size() ); + curMesh->mBones.push_back( ASE::Bone( bone ) ); } ParseLV4MeshFloat( me.second ); @@ -745,6 +744,7 @@ void Parser::ParseLV3MapBlock(Texture& map) // empty the texture won't be used later. // *********************************************************** bool parsePath = true; + std::string temp; while (true) { if ('*' == *filePtr) @@ -753,7 +753,7 @@ void Parser::ParseLV3MapBlock(Texture& map) // type of map if (TokenMatch(filePtr,"MAP_CLASS" ,9)) { - std::string temp; + temp.clear(); if(!ParseString(temp,"*MAP_CLASS")) SkipToNextToken(); if (temp != "Bitmap" && temp != "Normal Bump") diff --git a/code/BVHLoader.cpp b/code/BVHLoader.cpp index dfeeb60ac..0b2a818ae 100644 --- a/code/BVHLoader.cpp +++ b/code/BVHLoader.cpp @@ -199,6 +199,7 @@ aiNode* BVHLoader::ReadNode() Node& internNode = mNodes.back(); // now read the node's contents + std::string siteToken; while( 1) { std::string token = GetNextToken(); @@ -218,7 +219,8 @@ aiNode* BVHLoader::ReadNode() else if( token == "End") { // The real symbol is "End Site". Second part comes in a separate token - std::string siteToken = GetNextToken(); + siteToken.clear(); + siteToken = GetNextToken(); if( siteToken != "Site") ThrowException( format() << "Expected \"End Site\" keyword, but found \"" << token << " " << siteToken << "\"." ); @@ -262,21 +264,18 @@ aiNode* BVHLoader::ReadEndSite( const std::string& pParentName) aiNode* node = new aiNode( "EndSite_" + pParentName); // now read the node's contents. Only possible entry is "OFFSET" - while( 1) - { - std::string token = GetNextToken(); + std::string token; + while( 1) { + token.clear(); + token = GetNextToken(); // end node's offset - if( token == "OFFSET") - { + if( token == "OFFSET") { ReadNodeOffset( node); - } - else if( token == "}") - { + } else if( token == "}") { // we're done with the end node break; - } else - { + } else { // everything else is a parse error ThrowException( format() << "Unknown keyword \"" << token << "\"." ); } @@ -296,8 +295,10 @@ void BVHLoader::ReadNodeOffset( aiNode* pNode) offset.z = GetNextTokenAsFloat(); // build a transformation matrix from it - pNode->mTransformation = aiMatrix4x4( 1.0f, 0.0f, 0.0f, offset.x, 0.0f, 1.0f, 0.0f, offset.y, - 0.0f, 0.0f, 1.0f, offset.z, 0.0f, 0.0f, 0.0f, 1.0f); + pNode->mTransformation = aiMatrix4x4( 1.0f, 0.0f, 0.0f, offset.x, + 0.0f, 1.0f, 0.0f, offset.y, + 0.0f, 0.0f, 1.0f, offset.z, + 0.0f, 0.0f, 0.0f, 1.0f); } // ------------------------------------------------------------------------------------------------ diff --git a/code/BaseImporter.cpp b/code/BaseImporter.cpp index 67c743285..4782e9e2d 100644 --- a/code/BaseImporter.cpp +++ b/code/BaseImporter.cpp @@ -251,7 +251,8 @@ void BaseImporter::GetExtensionList(std::set& extensions) { /* static */ bool BaseImporter::CheckMagicToken(IOSystem* pIOHandler, const std::string& pFile, const void* _magic, unsigned int num, unsigned int offset, unsigned int size) { - ai_assert(size <= 16 && _magic); + ai_assert( size <= 16 ); + ai_assert( _magic ); if (!pIOHandler) { return false; diff --git a/code/ColladaExporter.cpp b/code/ColladaExporter.cpp index dc6b15ec4..96421a532 100644 --- a/code/ColladaExporter.cpp +++ b/code/ColladaExporter.cpp @@ -1269,7 +1269,8 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) mOutput << startstr << "" << endstr; PushTag(); - + + std::string node_idstr; for (size_t a = 0; a < anim->mNumChannels; ++a) { const aiNodeAnim * nodeAnim = anim->mChannels[a]; @@ -1277,7 +1278,9 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) if ( nodeAnim->mNumPositionKeys != nodeAnim->mNumScalingKeys || nodeAnim->mNumPositionKeys != nodeAnim->mNumRotationKeys ) continue; { - const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-input"); + node_idstr.clear(); + node_idstr += nodeAnim->mNodeName.data; + node_idstr += std::string( "_matrix-input" ); std::vector frames; for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) { @@ -1289,12 +1292,14 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) } { - const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-output"); + node_idstr.clear(); + + node_idstr += nodeAnim->mNodeName.data; + node_idstr += std::string("_matrix-output"); std::vector keyframes; keyframes.reserve(nodeAnim->mNumPositionKeys * 16); for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) { - aiVector3D Scaling = nodeAnim->mScalingKeys[i].mValue; aiMatrix4x4 ScalingM; // identity ScalingM[0][0] = Scaling.x; ScalingM[1][1] = Scaling.y; ScalingM[2][2] = Scaling.z; @@ -1361,7 +1366,6 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) PopTag(); mOutput << startstr << "" << endstr; } - } for (size_t a = 0; a < anim->mNumChannels; ++a) { diff --git a/code/ColladaLoader.cpp b/code/ColladaLoader.cpp index 959a905ae..01ba1c400 100644 --- a/code/ColladaLoader.cpp +++ b/code/ColladaLoader.cpp @@ -1121,6 +1121,7 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars continue; // now check all channels if they affect the current node + std::string targetID, subElement; for( std::vector::const_iterator cit = pSrcAnim->mChannels.begin(); cit != pSrcAnim->mChannels.end(); ++cit) { @@ -1147,7 +1148,9 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars } if( srcChannel.mTarget.find( '/', slashPos+1) != std::string::npos) continue; - std::string targetID = srcChannel.mTarget.substr( 0, slashPos); + + targetID.clear(); + targetID = srcChannel.mTarget.substr( 0, slashPos); if( targetID != srcNode->mID) continue; @@ -1160,7 +1163,8 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars entry.mTransformId = srcChannel.mTarget.substr( slashPos+1, dotPos - slashPos - 1); - std::string subElement = srcChannel.mTarget.substr( dotPos+1); + subElement.clear(); + subElement = srcChannel.mTarget.substr( dotPos+1); if( subElement == "ANGLE") entry.mSubElement = 3; // last number in an Axis-Angle-Transform is the angle else if( subElement == "X") @@ -1181,7 +1185,8 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars if (bracketPos != std::string::npos) { entry.mTransformId = srcChannel.mTarget.substr(slashPos + 1, bracketPos - slashPos - 1); - std::string subElement = srcChannel.mTarget.substr(bracketPos); + subElement.clear(); + subElement = srcChannel.mTarget.substr(bracketPos); if (subElement == "(0)(0)") entry.mSubElement = 0; @@ -1215,7 +1220,6 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars entry.mSubElement = 14; else if (subElement == "(3)(3)") entry.mSubElement = 15; - } // determine which transform step is affected by this channel diff --git a/code/D3MFExporter.cpp b/code/D3MFExporter.cpp index b89e81ce6..633f96ad9 100644 --- a/code/D3MFExporter.cpp +++ b/code/D3MFExporter.cpp @@ -211,20 +211,20 @@ void D3MFExporter::writeHeader() { void D3MFExporter::writeBaseMaterials() { mModelOutput << "\n"; + std::string strName, hexDiffuseColor , tmp; for ( size_t i = 0; i < mScene->mNumMaterials; ++i ) { aiMaterial *mat = mScene->mMaterials[ i ]; - std::string strName; aiString name; if ( mat->Get( AI_MATKEY_NAME, name ) != aiReturn_SUCCESS ) { strName = "basemat_" + to_string( i ); } else { strName = name.C_Str(); } - std::string hexDiffuseColor; aiColor4D color; if ( mat->Get( AI_MATKEY_COLOR_DIFFUSE, color ) == aiReturn_SUCCESS ) { + hexDiffuseColor.clear(); + tmp.clear(); hexDiffuseColor = "#"; - std::string tmp; tmp = DecimalToHexa( color.r ); hexDiffuseColor += tmp; diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index 3fffa5aeb..dc99f007e 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -94,8 +94,9 @@ public: scene->mRootNode = new aiNode(); std::vector children; + std::string nodeName; while(ReadToEndElement(D3MF::XmlTag::model)) { - const std::string nodeName( xmlReader->getNodeName() ); + nodeName = xmlReader->getNodeName(); if( nodeName == D3MF::XmlTag::object) { children.push_back(ReadObject(scene)); } else if( nodeName == D3MF::XmlTag::build) { diff --git a/code/D3MFOpcPackage.cpp b/code/D3MFOpcPackage.cpp index 2f7c8a25e..3bf545813 100644 --- a/code/D3MFOpcPackage.cpp +++ b/code/D3MFOpcPackage.cpp @@ -288,8 +288,8 @@ bool D3MFZipArchive::Exists(const char* pFile) const { return false; } - std::string rFile(pFile); - std::map::const_iterator it = m_ArchiveMap.find(rFile); + std::string filename(pFile); + std::map::const_iterator it = m_ArchiveMap.find(filename); bool exist( false ); if(it != m_ArchiveMap.end()) { exist = true; diff --git a/code/DXFHelper.h b/code/DXFHelper.h index 5aaf4844f..49ca2814d 100644 --- a/code/DXFHelper.h +++ b/code/DXFHelper.h @@ -169,7 +169,6 @@ public: } private: - LineSplitter splitter; int groupcode; std::string value; diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 9bb023b4e..537a4f558 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -1642,9 +1642,8 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap& } void Converter::TrySetTextureProperties( aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, - const std::string& propName, - aiTextureType target, const MeshGeometry* const mesh ) -{ + const std::string& propName, + aiTextureType target, const MeshGeometry* const mesh ) { LayeredTextureMap::const_iterator it = layeredTextures.find( propName ); if ( it == layeredTextures.end() ) { return; diff --git a/code/Importer.cpp b/code/Importer.cpp index feddadf58..6422ca6d0 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -622,7 +622,6 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) if (s != std::string::npos) { DefaultLogger::get()->info("File extension not known, trying signature-based detection"); for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) { - if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, true)) { imp = pimpl->mImporter[a]; break; @@ -947,6 +946,7 @@ BaseImporter* Importer::GetImporter (const char* szExtension) const size_t Importer::GetImporterIndex (const char* szExtension) const { ai_assert(szExtension); + ASSIMP_BEGIN_EXCEPTION_REGION(); // skip over wildcard and dot characters at string head -- diff --git a/code/SceneCombiner.cpp b/code/SceneCombiner.cpp index 8647bd1ba..240dbbb12 100644 --- a/code/SceneCombiner.cpp +++ b/code/SceneCombiner.cpp @@ -806,8 +806,9 @@ void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/, for (std::vector::const_iterator it = begin; it != end;++it) { if ((*it)->mNormals) { ::memcpy(pv2,(*it)->mNormals,(*it)->mNumVertices*sizeof(aiVector3D)); + } else { + DefaultLogger::get()->warn( "JoinMeshes: Normals expected but input mesh contains no normals" ); } - else DefaultLogger::get()->warn("JoinMeshes: Normals expected but input mesh contains no normals"); pv2 += (*it)->mNumVertices; } } @@ -817,28 +818,29 @@ void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/, pv2 = out->mTangents = new aiVector3D[out->mNumVertices]; aiVector3D* pv2b = out->mBitangents = new aiVector3D[out->mNumVertices]; - for (std::vector::const_iterator it = begin; it != end;++it) { + for (std::vector::const_iterator it = begin; it != end;++it) { if ((*it)->mTangents) { ::memcpy(pv2, (*it)->mTangents, (*it)->mNumVertices*sizeof(aiVector3D)); ::memcpy(pv2b,(*it)->mBitangents,(*it)->mNumVertices*sizeof(aiVector3D)); + } else { + DefaultLogger::get()->warn( "JoinMeshes: Tangents expected but input mesh contains no tangents" ); } - else DefaultLogger::get()->warn("JoinMeshes: Tangents expected but input mesh contains no tangents"); pv2 += (*it)->mNumVertices; pv2b += (*it)->mNumVertices; } } // copy texture coordinates unsigned int n = 0; - while ((**begin).HasTextureCoords(n)) { + while ((**begin).HasTextureCoords(n)) { out->mNumUVComponents[n] = (*begin)->mNumUVComponents[n]; pv2 = out->mTextureCoords[n] = new aiVector3D[out->mNumVertices]; for (std::vector::const_iterator it = begin; it != end;++it) { - if ((*it)->mTextureCoords[n]) { ::memcpy(pv2,(*it)->mTextureCoords[n],(*it)->mNumVertices*sizeof(aiVector3D)); + } else { + DefaultLogger::get()->warn( "JoinMeshes: UVs expected but input mesh contains no UVs" ); } - else DefaultLogger::get()->warn("JoinMeshes: UVs expected but input mesh contains no UVs"); pv2 += (*it)->mNumVertices; } ++n; @@ -848,11 +850,11 @@ void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/, while ((**begin).HasVertexColors(n)) { aiColor4D* pv2 = out->mColors[n] = new aiColor4D[out->mNumVertices]; for (std::vector::const_iterator it = begin; it != end;++it) { - if ((*it)->mColors[n]) { ::memcpy(pv2,(*it)->mColors[n],(*it)->mNumVertices*sizeof(aiColor4D)); + } else { + DefaultLogger::get()->warn( "JoinMeshes: VCs expected but input mesh contains no VCs" ); } - else DefaultLogger::get()->warn("JoinMeshes: VCs expected but input mesh contains no VCs"); pv2 += (*it)->mNumVertices; } ++n; diff --git a/include/assimp/DefaultLogger.hpp b/include/assimp/DefaultLogger.hpp index d6a88b0f3..1f0c899be 100644 --- a/include/assimp/DefaultLogger.hpp +++ b/include/assimp/DefaultLogger.hpp @@ -131,9 +131,7 @@ public: bool detatchStream(LogStream *pStream, unsigned int severity); - private: - // ---------------------------------------------------------------------- /** @briefPrivate construction for internal use by create(). * @param severity Logging granularity */ @@ -143,8 +141,6 @@ private: /** @briefDestructor */ ~DefaultLogger(); -private: - /** @brief Logs debug infos, only been written when severity level VERBOSE is set */ void OnDebug(const char* message); From d0edb942087795887e347a60755f1ef8e9be95f7 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 20 Mar 2018 20:38:03 +0100 Subject: [PATCH 097/278] Update D3MFImporter.cpp Use static cast instead of c-cast. --- code/D3MFImporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index 535652502..c46685b45 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -282,7 +282,7 @@ private: MatIdArray = it->second; } } - MatIdArray.push_back( (unsigned int)newMatIdx ); + MatIdArray.push_back( static_cast( newMatIdx ) ); mMatId2MatArray[ mActiveMatGroup ] = MatIdArray; } From 339e33303e6af97cd986ddffe70ad753076cc990 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 20 Mar 2018 20:39:15 +0100 Subject: [PATCH 098/278] Update DefaultIOSystem.cpp Use static_cast instead of int. --- code/DefaultIOSystem.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/DefaultIOSystem.cpp b/code/DefaultIOSystem.cpp index 6e9c0321e..d65681b9b 100644 --- a/code/DefaultIOSystem.cpp +++ b/code/DefaultIOSystem.cpp @@ -76,7 +76,7 @@ bool DefaultIOSystem::Exists( const char* pFile) const #ifdef _WIN32 wchar_t fileName16[PATHLIMIT]; - bool isUnicode = IsTextUnicode(pFile, int(strlen(pFile)), NULL); + bool isUnicode = IsTextUnicode(pFile, static_cast(strlen(pFile)), NULL); if (isUnicode) { MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, pFile, -1, fileName16, PATHLIMIT); @@ -110,7 +110,7 @@ IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode) FILE* file; #ifdef _WIN32 wchar_t fileName16[PATHLIMIT]; - bool isUnicode = IsTextUnicode(strFile, int(strlen(strFile)), NULL ); + bool isUnicode = IsTextUnicode(strFile, static_cast(strlen(strFile)), NULL ); if (isUnicode) { MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, strFile, -1, fileName16, PATHLIMIT); std::string mode8(strMode); @@ -158,7 +158,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out) { ai_assert(in && _out); #if defined( _MSC_VER ) || defined( __MINGW32__ ) - bool isUnicode = IsTextUnicode(in, int(strlen(in)), NULL); + bool isUnicode = IsTextUnicode(in, static_cast(strlen(in)), NULL); if (isUnicode) { wchar_t out16[PATHLIMIT]; wchar_t in16[PATHLIMIT]; From b01594f6a82c899fec8dfd4f81c5c4ee852d7129 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 20 Mar 2018 21:52:42 +0100 Subject: [PATCH 099/278] Update EmbedTexturesProcess.cpp Replace c-cast by static_cast. --- code/EmbedTexturesProcess.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/EmbedTexturesProcess.cpp b/code/EmbedTexturesProcess.cpp index b434d79d7..27313869d 100644 --- a/code/EmbedTexturesProcess.cpp +++ b/code/EmbedTexturesProcess.cpp @@ -134,7 +134,7 @@ bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const { // Add the new texture auto pTexture = new aiTexture(); pTexture->mHeight = 0; // Means that this is still compressed - pTexture->mWidth = uint32_t(imageSize); + pTexture->mWidth = static_cats(imageSize); pTexture->pcData = imageContent; auto extension = path.substr(path.find_last_of('.') + 1u); From 1a887a64c193abde8b1f64b7981df19704c0d0f3 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 20 Mar 2018 21:56:26 +0100 Subject: [PATCH 100/278] Update EmbedTexturesProcess.cpp Fix typo. --- code/EmbedTexturesProcess.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/EmbedTexturesProcess.cpp b/code/EmbedTexturesProcess.cpp index 27313869d..076339468 100644 --- a/code/EmbedTexturesProcess.cpp +++ b/code/EmbedTexturesProcess.cpp @@ -134,7 +134,7 @@ bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const { // Add the new texture auto pTexture = new aiTexture(); pTexture->mHeight = 0; // Means that this is still compressed - pTexture->mWidth = static_cats(imageSize); + pTexture->mWidth = static_cast(imageSize); pTexture->pcData = imageContent; auto extension = path.substr(path.find_last_of('.') + 1u); From 4ae7298489921ead2e3b2e500feec888846eff9f Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 20 Mar 2018 21:59:45 +0100 Subject: [PATCH 101/278] Update DefaultIOSystem.cpp fix typo --- code/DefaultIOSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/DefaultIOSystem.cpp b/code/DefaultIOSystem.cpp index d65681b9b..36c14e41d 100644 --- a/code/DefaultIOSystem.cpp +++ b/code/DefaultIOSystem.cpp @@ -76,7 +76,7 @@ bool DefaultIOSystem::Exists( const char* pFile) const #ifdef _WIN32 wchar_t fileName16[PATHLIMIT]; - bool isUnicode = IsTextUnicode(pFile, static_cast(strlen(pFile)), NULL); + bool isUnicode = IsTextUnicode(pFile, static_cast(strlen(pFile)), NULL); if (isUnicode) { MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, pFile, -1, fileName16, PATHLIMIT); From af3bba15726f586d4b43bfa9bab2b9b7535dd7ce Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 20 Mar 2018 23:38:08 +0100 Subject: [PATCH 102/278] fix review findings. --- code/Importer/IFC/IFCLoader.cpp | 5 ++- code/ObjExporter.cpp | 27 ++++++++------- code/ObjFileImporter.cpp | 30 ++++++----------- code/ObjFileParser.cpp | 7 ++-- code/OgreParsingUtils.h | 55 +++++++++++++------------------ code/OgreXmlSerializer.cpp | 19 +++++------ include/assimp/ParsingUtils.h | 53 ++++++++++++++++------------- include/assimp/StringComparison.h | 41 +++++++++++++---------- include/assimp/StringUtils.h | 12 ++++--- 9 files changed, 122 insertions(+), 127 deletions(-) diff --git a/code/Importer/IFC/IFCLoader.cpp b/code/Importer/IFC/IFCLoader.cpp index 5acc89545..9faf68cbb 100644 --- a/code/Importer/IFC/IFCLoader.cpp +++ b/code/Importer/IFC/IFCLoader.cpp @@ -583,9 +583,8 @@ typedef std::map Metadata; // ------------------------------------------------------------------------------------------------ void ProcessMetadata(const Schema_2x3::ListOf< Schema_2x3::Lazy< Schema_2x3::IfcProperty >, 1, 0 >& set, ConversionData& conv, Metadata& properties, - const std::string& prefix = "", - unsigned int nest = 0) -{ + const std::string& prefix = "", + unsigned int nest = 0) { for(const Schema_2x3::IfcProperty& property : set) { const std::string& key = prefix.length() > 0 ? (prefix + "." + property.Name) : property.Name; if (const Schema_2x3::IfcPropertySingleValue* const singleValue = property.ToPtr()) { diff --git a/code/ObjExporter.cpp b/code/ObjExporter.cpp index 9beb418f3..d08b5f859 100644 --- a/code/ObjExporter.cpp +++ b/code/ObjExporter.cpp @@ -132,18 +132,18 @@ ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMt mOutputMat.precision(16); WriteGeometryFile(noMtl); - if (!noMtl) + if ( !noMtl ) { WriteMaterialFile(); + } } // ------------------------------------------------------------------------------------------------ ObjExporter::~ObjExporter() { - + // empty } // ------------------------------------------------------------------------------------------------ -std::string ObjExporter :: GetMaterialLibName() -{ +std::string ObjExporter::GetMaterialLibName() { // within the Obj file, we use just the relative file name with the path stripped const std::string& s = GetMaterialLibFileName(); std::string::size_type il = s.find_last_of("/\\"); @@ -158,8 +158,9 @@ std::string ObjExporter :: GetMaterialLibName() std::string ObjExporter::GetMaterialLibFileName() { // Remove existing .obj file extension so that the final material file name will be fileName.mtl and not fileName.obj.mtl size_t lastdot = filename.find_last_of('.'); - if (lastdot != std::string::npos) - return filename.substr(0, lastdot) + MaterialExt; + if ( lastdot != std::string::npos ) { + return filename.substr( 0, lastdot ) + MaterialExt; + } return filename + MaterialExt; } @@ -172,8 +173,7 @@ void ObjExporter::WriteHeader(std::ostringstream& out) { } // ------------------------------------------------------------------------------------------------ -std::string ObjExporter::GetMaterialName(unsigned int index) -{ +std::string ObjExporter::GetMaterialName(unsigned int index) { const aiMaterial* const mat = pScene->mMaterials[index]; if ( nullptr == mat ) { static const std::string EmptyStr; @@ -191,8 +191,7 @@ std::string ObjExporter::GetMaterialName(unsigned int index) } // ------------------------------------------------------------------------------------------------ -void ObjExporter::WriteMaterialFile() -{ +void ObjExporter::WriteMaterialFile() { WriteHeader(mOutputMat); for(unsigned int i = 0; i < pScene->mNumMaterials; ++i) { @@ -310,8 +309,9 @@ void ObjExporter::WriteGeometryFile(bool noMtl) { if (!m.name.empty()) { mOutput << "g " << m.name << endl; } - if (!noMtl) + if ( !noMtl ) { mOutput << "usemtl " << m.matname << endl; + } for(const Face& f : m.faces) { mOutput << f.kind << ' '; @@ -382,7 +382,7 @@ void ObjExporter::colIndexMap::getColors( std::vector &colors ) { // ------------------------------------------------------------------------------------------------ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) { - mMeshes.push_back(MeshInstance()); + mMeshes.push_back(MeshInstance() ); MeshInstance& mesh = mMeshes.back(); mesh.name = std::string( name.data, name.length ); @@ -436,8 +436,7 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4 } // ------------------------------------------------------------------------------------------------ -void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent) -{ +void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent) { const aiMatrix4x4& mAbs = mParent * nd->mTransformation; for(unsigned int i = 0; i < nd->mNumMeshes; ++i) { diff --git a/code/ObjFileImporter.cpp b/code/ObjFileImporter.cpp index 02d6ac581..bce94ebbb 100644 --- a/code/ObjFileImporter.cpp +++ b/code/ObjFileImporter.cpp @@ -207,30 +207,24 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene // Create the root node of the scene pScene->mRootNode = new aiNode; - if ( !pModel->m_ModelName.empty() ) - { + if ( !pModel->m_ModelName.empty() ) { // Set the name of the scene pScene->mRootNode->mName.Set(pModel->m_ModelName); - } - else - { + } else { // This is a fatal error, so break down the application ai_assert(false); } // Create nodes for the whole scene std::vector MeshArray; - for (size_t index = 0; index < pModel->m_Objects.size(); index++) - { + for (size_t index = 0; index < pModel->m_Objects.size(); ++index ) { createNodes(pModel, pModel->m_Objects[ index ], pScene->mRootNode, pScene, MeshArray); } // Create mesh pointer buffer for this scene - if (pScene->mNumMeshes > 0) - { + if (pScene->mNumMeshes > 0) { pScene->mMeshes = new aiMesh*[ MeshArray.size() ]; - for (size_t index =0; index < MeshArray.size(); index++) - { + for (size_t index =0; index < MeshArray.size(); ++index ) { pScene->mMeshes[ index ] = MeshArray[ index ]; } } @@ -261,8 +255,7 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile appendChildToParentNode( pParent, pNode ); } - for ( size_t i=0; i< pObject->m_Meshes.size(); i++ ) - { + for ( size_t i=0; i< pObject->m_Meshes.size(); ++i ) { unsigned int meshId = pObject->m_Meshes[ i ]; aiMesh *pMesh = createTopology( pModel, pObject, meshId ); if( pMesh ) { @@ -275,8 +268,7 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile } // Create all nodes from the sub-objects stored in the current object - if ( !pObject->m_SubObjects.empty() ) - { + if ( !pObject->m_SubObjects.empty() ) { size_t numChilds = pObject->m_SubObjects.size(); pNode->mNumChildren = static_cast( numChilds ); pNode->mChildren = new aiNode*[ numChilds ]; @@ -286,16 +278,14 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile // Set mesh instances into scene- and node-instances const size_t meshSizeDiff = MeshArray.size()- oldMeshSize; - if ( meshSizeDiff > 0 ) - { + if ( meshSizeDiff > 0 ) { pNode->mMeshes = new unsigned int[ meshSizeDiff ]; pNode->mNumMeshes = static_cast( meshSizeDiff ); size_t index = 0; - for (size_t i = oldMeshSize; i < MeshArray.size(); i++) - { + for (size_t i = oldMeshSize; i < MeshArray.size(); ++i ) { pNode->mMeshes[ index ] = pScene->mNumMeshes; pScene->mNumMeshes++; - index++; + ++index; } } diff --git a/code/ObjFileParser.cpp b/code/ObjFileParser.cpp index ae95edbcb..7cd2d36c2 100644 --- a/code/ObjFileParser.cpp +++ b/code/ObjFileParser.cpp @@ -612,13 +612,14 @@ void ObjFileParser::getMaterialLib() { if ( '/' != *path.rbegin() ) { path += '/'; } - absName = path + strMatName; + absName += path; + absName += strMatName; } else { absName = strMatName; } - IOStream *pFile = m_pIO->Open( absName ); - if (!pFile ) { + IOStream *pFile = m_pIO->Open( absName ); + if ( nullptr == pFile ) { DefaultLogger::get()->error("OBJ: Unable to locate material file " + strMatName); std::string strMatFallbackName = m_originalObjFileName.substr(0, m_originalObjFileName.length() - 3) + "mtl"; DefaultLogger::get()->info("OBJ: Opening fallback material file " + strMatFallbackName); diff --git a/code/OgreParsingUtils.h b/code/OgreParsingUtils.h index a77b94121..c6b6e0caf 100644 --- a/code/OgreParsingUtils.h +++ b/code/OgreParsingUtils.h @@ -52,27 +52,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -namespace Assimp -{ -namespace Ogre -{ +namespace Assimp { +namespace Ogre { /// Returns a lower cased copy of @s. -static inline std::string ToLower(std::string s) +static AI_FORCE_INLINE +std::string ToLower(std::string s) { std::transform(s.begin(), s.end(), s.begin(), ::tolower); return s; } /// Returns if @c s ends with @c suffix. If @c caseSensitive is false, both strings will be lower cased before matching. -static inline bool EndsWith(const std::string &s, const std::string &suffix, bool caseSensitive = true) -{ - if (s.empty() || suffix.empty()) - { +static AI_FORCE_INLINE +bool EndsWith(const std::string &s, const std::string &suffix, bool caseSensitive = true) { + if (s.empty() || suffix.empty()) { return false; - } - else if (s.length() < suffix.length()) - { + } else if (s.length() < suffix.length()) { return false; } @@ -82,48 +78,43 @@ static inline bool EndsWith(const std::string &s, const std::string &suffix, boo size_t len = suffix.length(); std::string sSuffix = s.substr(s.length()-len, len); + return (ASSIMP_stricmp(sSuffix, suffix) == 0); } // Below trim functions adapted from http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring /// Trim from start -static inline std::string &TrimLeft(std::string &s, bool newlines = true) -{ - if (!newlines) - { +static AI_FORCE_INLINE +std::string &TrimLeft(std::string &s, bool newlines = true) { + if (!newlines) { s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpace(c); })); - } - else - { + } else { s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpaceOrNewLine(c); })); } return s; } /// Trim from end -static inline std::string &TrimRight(std::string &s, bool newlines = true) -{ - if (!newlines) - { +static AI_FORCE_INLINE +std::string &TrimRight(std::string &s, bool newlines = true) { + if (!newlines) { s.erase(std::find_if(s.rbegin(), s.rend(), [](char c) { return !Assimp::IsSpace(c); }).base(),s.end()); - } - else - { + } else { s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpaceOrNewLine(c); })); } return s; } /// Trim from both ends -static inline std::string &Trim(std::string &s, bool newlines = true) -{ +static AI_FORCE_INLINE +std::string &Trim(std::string &s, bool newlines = true) { return TrimLeft(TrimRight(s, newlines), newlines); } /// Skips a line from current @ss position until a newline. Returns the skipped part. -static inline std::string SkipLine(std::stringstream &ss) -{ +static AI_FORCE_INLINE +std::string SkipLine(std::stringstream &ss) { std::string skipped; getline(ss, skipped); return skipped; @@ -131,8 +122,8 @@ static inline std::string SkipLine(std::stringstream &ss) /// Skips a line and reads next element from @c ss to @c nextElement. /** @return Skipped line content until newline. */ -static inline std::string NextAfterNewLine(std::stringstream &ss, std::string &nextElement) -{ +static AI_FORCE_INLINE +std::string NextAfterNewLine(std::stringstream &ss, std::string &nextElement) { std::string skipped = SkipLine(ss); ss >> nextElement; return skipped; diff --git a/code/OgreXmlSerializer.cpp b/code/OgreXmlSerializer.cpp index 78acaa7fd..12b2bcbd9 100644 --- a/code/OgreXmlSerializer.cpp +++ b/code/OgreXmlSerializer.cpp @@ -213,18 +213,18 @@ std::string &OgreXmlSerializer::SkipCurrentNode() DefaultLogger::get()->debug("Skipping node <" + m_currentNodeName + ">"); #endif - for(;;) - { - if (!m_reader->read()) - { + for(;;) { + if (!m_reader->read()) { m_currentNodeName = ""; return m_currentNodeName; } - if (m_reader->getNodeType() != irr::io::EXN_ELEMENT_END) + if ( m_reader->getNodeType() != irr::io::EXN_ELEMENT_END ) { continue; - else if (std::string(m_reader->getNodeName()) == m_currentNodeName) + } else if ( std::string( m_reader->getNodeName() ) == m_currentNodeName ) { break; + } } + return NextNode(); } @@ -303,17 +303,16 @@ static const char *anZ = "z"; // Mesh -MeshXml *OgreXmlSerializer::ImportMesh(XmlReader *reader) -{ +MeshXml *OgreXmlSerializer::ImportMesh(XmlReader *reader) { OgreXmlSerializer serializer(reader); MeshXml *mesh = new MeshXml(); serializer.ReadMesh(mesh); + return mesh; } -void OgreXmlSerializer::ReadMesh(MeshXml *mesh) -{ +void OgreXmlSerializer::ReadMesh(MeshXml *mesh) { if (NextNode() != nnMesh) { throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting "); } diff --git a/include/assimp/ParsingUtils.h b/include/assimp/ParsingUtils.h index 40e183a5c..4553072db 100644 --- a/include/assimp/ParsingUtils.h +++ b/include/assimp/ParsingUtils.h @@ -115,8 +115,8 @@ bool IsSpaceOrNewLine( char_t in) { // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool SkipSpaces( const char_t* in, const char_t** out) -{ +AI_FORCE_INLINE +bool SkipSpaces( const char_t* in, const char_t** out) { while( *in == ( char_t )' ' || *in == ( char_t )'\t' ) { ++in; } @@ -126,15 +126,15 @@ AI_FORCE_INLINE bool SkipSpaces( const char_t* in, const char_t** out) // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool SkipSpaces( const char_t** inout) -{ +AI_FORCE_INLINE +bool SkipSpaces( const char_t** inout) { return SkipSpaces(*inout,inout); } // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool SkipLine( const char_t* in, const char_t** out) -{ +AI_FORCE_INLINE +bool SkipLine( const char_t* in, const char_t** out) { while( *in != ( char_t )'\r' && *in != ( char_t )'\n' && *in != ( char_t )'\0' ) { ++in; } @@ -149,15 +149,15 @@ AI_FORCE_INLINE bool SkipLine( const char_t* in, const char_t** out) // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool SkipLine( const char_t** inout) -{ +AI_FORCE_INLINE +bool SkipLine( const char_t** inout) { return SkipLine(*inout,inout); } // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out) -{ +AI_FORCE_INLINE +bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out) { while( *in == ( char_t )' ' || *in == ( char_t )'\t' || *in == ( char_t )'\r' || *in == ( char_t )'\n' ) { ++in; } @@ -167,15 +167,15 @@ AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out) // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t** inout) -{ +AI_FORCE_INLINE +bool SkipSpacesAndLineEnd( const char_t** inout) { return SkipSpacesAndLineEnd(*inout,inout); } // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool GetNextLine( const char_t*& buffer, char_t out[ BufferSize ] ) -{ +AI_FORCE_INLINE +bool GetNextLine( const char_t*& buffer, char_t out[ BufferSize ] ) { if( ( char_t )'\0' == *buffer ) { return false; } @@ -203,7 +203,8 @@ AI_FORCE_INLINE bool IsNumeric( char_t in) // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool TokenMatch(char_t*& in, const char* token, unsigned int len) +AI_FORCE_INLINE +bool TokenMatch(char_t*& in, const char* token, unsigned int len) { if (!::strncmp(token,in,len) && IsSpaceOrNewLine(in[len])) { if (in[len] != '\0') { @@ -223,26 +224,32 @@ AI_FORCE_INLINE bool TokenMatch(char_t*& in, const char* token, unsigned int len * @param token Token to check for * @param len Number of characters to check */ -AI_FORCE_INLINE bool TokenMatchI(const char*& in, const char* token, unsigned int len) -{ +AI_FORCE_INLINE +bool TokenMatchI(const char*& in, const char* token, unsigned int len) { if (!ASSIMP_strincmp(token,in,len) && IsSpaceOrNewLine(in[len])) { in += len+1; return true; } return false; } + // --------------------------------------------------------------------------------- -AI_FORCE_INLINE void SkipToken(const char*& in) -{ +AI_FORCE_INLINE +void SkipToken(const char*& in) { SkipSpaces(&in); - while (!IsSpaceOrNewLine(*in))++in; + while ( !IsSpaceOrNewLine( *in ) ) { + ++in; + } } + // --------------------------------------------------------------------------------- -AI_FORCE_INLINE std::string GetNextToken(const char*& in) -{ +AI_FORCE_INLINE +std::string GetNextToken(const char*& in) { SkipSpacesAndLineEnd(&in); const char* cur = in; - while (!IsSpaceOrNewLine(*in))++in; + while ( !IsSpaceOrNewLine( *in ) ) { + ++in; + } return std::string(cur,(size_t)(in-cur)); } diff --git a/include/assimp/StringComparison.h b/include/assimp/StringComparison.h index 1fada49dd..aea7f001a 100644 --- a/include/assimp/StringComparison.h +++ b/include/assimp/StringComparison.h @@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INCLUDED_AI_STRING_WORKERS_H #include +#include #include "StringComparison.h" #include @@ -72,8 +73,8 @@ namespace Assimp { * @param number Number to be written * @return Length of the output string, excluding the '\0' */ -inline unsigned int ASSIMP_itoa10( char* out, unsigned int max, int32_t number) -{ +AI_FORCE_INLINE +unsigned int ASSIMP_itoa10( char* out, unsigned int max, int32_t number) { ai_assert(NULL != out); // write the unary minus to indicate we have a negative number @@ -91,7 +92,7 @@ inline unsigned int ASSIMP_itoa10( char* out, unsigned int max, int32_t number) const unsigned int digit = number / cur; if (mustPrint || digit > 0 || 1 == cur) { - // print all future zeroes from now + // print all future zeroe's from now mustPrint = true; *out++ = '0'+static_cast(digit); @@ -116,8 +117,8 @@ inline unsigned int ASSIMP_itoa10( char* out, unsigned int max, int32_t number) * size of the array automatically. */ template -inline unsigned int ASSIMP_itoa10( char(& out)[length], int32_t number) -{ +AI_FORCE_INLINE +unsigned int ASSIMP_itoa10( char(& out)[length], int32_t number) { return ASSIMP_itoa10(out,length,number); } @@ -132,9 +133,10 @@ inline unsigned int ASSIMP_itoa10( char(& out)[length], int32_t number) * @param s2 Second input string * @return 0 if the given strings are identical */ -inline int ASSIMP_stricmp(const char *s1, const char *s2) -{ - ai_assert(NULL != s1 && NULL != s2); +AI_FORCE_INLINE +int ASSIMP_stricmp(const char *s1, const char *s2) { + ai_assert( NULL != s1 ); + ai_assert( NULL != s2 ); #if (defined _MSC_VER) @@ -161,8 +163,8 @@ inline int ASSIMP_stricmp(const char *s1, const char *s2) * @param b Second string * @return 0 if a == b */ -inline int ASSIMP_stricmp(const std::string& a, const std::string& b) -{ +AI_FORCE_INLINE +int ASSIMP_stricmp(const std::string& a, const std::string& b) { int i = (int)b.length()-(int)a.length(); return (i ? i : ASSIMP_stricmp(a.c_str(),b.c_str())); } @@ -179,10 +181,13 @@ inline int ASSIMP_stricmp(const std::string& a, const std::string& b) * @param n Macimum number of characters to compare * @return 0 if the given strings are identical */ -inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n) -{ - ai_assert(NULL != s1 && NULL != s2); - if (!n)return 0; +AI_FORCE_INLINE +int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n) { + ai_assert( NULL != s1 ); + ai_assert( NULL != s2 ); + if ( !n ) { + return 0; + } #if (defined _MSC_VER) @@ -213,14 +218,16 @@ inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n) * * todo: move somewhere where it fits better in than here */ -inline unsigned int integer_pow (unsigned int base, unsigned int power) -{ +AI_FORCE_INLINE +unsigned int integer_pow( unsigned int base, unsigned int power ) { unsigned int res = 1; - for (unsigned int i = 0; i < power;++i) + for ( unsigned int i = 0; i < power; ++i ) { res *= base; + } return res; } + } // end of namespace #endif // ! AI_STRINGCOMPARISON_H_INC diff --git a/include/assimp/StringUtils.h b/include/assimp/StringUtils.h index 157454126..906898b53 100644 --- a/include/assimp/StringUtils.h +++ b/include/assimp/StringUtils.h @@ -42,6 +42,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef INCLUDED_AI_STRINGUTILS_H #define INCLUDED_AI_STRINGUTILS_H +#include + #include #include #include @@ -55,7 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /// @return The number of written characters if the buffer size was big enough. If an encoding error occurs, a negative number is returned. #if defined(_MSC_VER) && _MSC_VER < 1900 - inline + AI_FORCE_INLINE int c99_ai_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) { int count(-1); if (0 != size) { @@ -68,7 +70,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return count; } - inline + AI_FORCE_INLINE int ai_snprintf(char *outBuf, size_t size, const char *format, ...) { int count; va_list ap; @@ -89,7 +91,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /// @param value The value to write into the std::string. /// @return The value as a std::string template -inline +AI_FORCE_INLINE std::string to_string( T value ) { std::ostringstream os; os << value; @@ -102,7 +104,7 @@ std::string to_string( T value ) { /// @param begin The first character of the string. /// @param end The last character /// @return The float value, 0.0f in cas of an error. -inline +AI_FORCE_INLINE float ai_strtof( const char *begin, const char *end ) { if ( nullptr == begin ) { return 0.0f; @@ -124,7 +126,7 @@ float ai_strtof( const char *begin, const char *end ) { /// @param toConvert Value to convert /// @return The hexadecimal string, is empty in case of an error. template -inline +AI_FORCE_INLINE std::string DecimalToHexa( T toConvert ) { std::string result; std::stringstream ss; From efd4a6c37103ef66210cac53026890f45ec29b9f Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 21 Mar 2018 20:31:04 +0100 Subject: [PATCH 103/278] Update Readme.md - Fix broken link - Update list with supported importers + exporters --- Readme.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index a6f2e3d3d..4ee8a0e90 100644 --- a/Readme.md +++ b/Readme.md @@ -32,8 +32,8 @@ Please check our Wiki as well: https://github.com/assimp/assimp/wiki #### Supported file formats #### -A full list [is here](http://assimp.org/main_features_formats.html). __Importers__: + - 3D - 3DS - 3MF @@ -109,6 +109,8 @@ __Exporters__: - STEP - glTF 1.0 (partial) - glTF 2.0 (partial) +- 3MF ( experimental ) +- FBX ( experimental ) ### Building ### Take a look into the `INSTALL` file. Our build system is CMake, if you used CMake before there is a good chance you know what to do. From cad11df0394b6a4f9f5f2e5f945f605ea8cd44df Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Thu, 22 Mar 2018 16:54:12 +0800 Subject: [PATCH 104/278] Fix mingw compilation --- code/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 6e2db91db..dafe017ef 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -485,9 +485,9 @@ ADD_ASSIMP_IMPORTER( IFC ) if (ASSIMP_BUILD_IFC_IMPORTER) if (MSVC) - set_source_files_properties(IFCReaderGen1.cpp IFCReaderGen2.cpp PROPERTIES COMPILE_FLAGS "/bigobj") + set_source_files_properties(Importer/IFC/IFCReaderGen1_2x3.cpp Importer/IFC/IFCReaderGen2_2x3.cpp PROPERTIES COMPILE_FLAGS "/bigobj") elseif(CMAKE_COMPILER_IS_MINGW) - set_source_files_properties(IFCReaderGen1.cpp IFCReaderGen2.cpp PROPERTIES COMPILE_FLAGS "-O2 -Wa,-mbig-obj") + set_source_files_properties(Importer/IFC/IFCReaderGen1_2x3.cpp Importer/IFC/IFCReaderGen2_2x3.cpp PROPERTIES COMPILE_FLAGS "-O2 -Wa,-mbig-obj") endif() endif (ASSIMP_BUILD_IFC_IMPORTER) From 6c21a30958b718e78144e2f492563f07d1ca6bf4 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 22 Mar 2018 20:07:47 +0100 Subject: [PATCH 105/278] closes https://github.com/assimp/assimp/issues/1850: remove buggy setup in cmake. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 15374a3fb..fe4239351 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,7 +110,7 @@ if (WIN32) endif() IF(MSVC) - SET (CMAKE_PREFIX_PATH "D:\\libs\\devil") +# SET (CMAKE_PREFIX_PATH "D:\\libs\\devil") OPTION( ASSIMP_INSTALL_PDB "Install MSVC debug files." ON From 349d877899ea855e68a1baa0a01a1a5ebeb2bd17 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 22 Mar 2018 21:28:52 +0100 Subject: [PATCH 106/278] Update CMakeLists.txt Remove dead code. --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fe4239351..0026dcb7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,7 +110,6 @@ if (WIN32) endif() IF(MSVC) -# SET (CMAKE_PREFIX_PATH "D:\\libs\\devil") OPTION( ASSIMP_INSTALL_PDB "Install MSVC debug files." ON From 13ae0a0ac3a1f464158b24e341fe2a889ce48904 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 22 Mar 2018 22:14:10 +0100 Subject: [PATCH 107/278] FBX: fix parse error for uv-coordinates. --- code/FBXMeshGeometry.cpp | 25 ++++++++++---------- code/FBXMeshGeometry.h | 5 ++-- include/assimp/IOStreamBuffer.h | 41 +++++++++++++++++---------------- 3 files changed, 35 insertions(+), 36 deletions(-) diff --git a/code/FBXMeshGeometry.cpp b/code/FBXMeshGeometry.cpp index 6f7b84d96..12001f76c 100644 --- a/code/FBXMeshGeometry.cpp +++ b/code/FBXMeshGeometry.cpp @@ -79,14 +79,13 @@ Geometry::Geometry(uint64_t id, const Element& element, const std::string& name, // ------------------------------------------------------------------------------------------------ Geometry::~Geometry() { - + // empty } const Skin* Geometry::DeformerSkin() const { return skin; } - // ------------------------------------------------------------------------------------------------ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc) : Geometry(id, element,name, doc) @@ -186,9 +185,8 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin } // ------------------------------------------------------------------------------------------------ -MeshGeometry::~MeshGeometry() -{ - +MeshGeometry::~MeshGeometry() { + // empty } // ------------------------------------------------------------------------------------------------ @@ -218,7 +216,7 @@ const std::vector& MeshGeometry::GetFaceIndexCounts() const { // ------------------------------------------------------------------------------------------------ const std::vector& MeshGeometry::GetTextureCoords( unsigned int index ) const { - static const std::vector empty; + const std::vector empty; return index >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? empty : m_uvs[ index ]; } @@ -227,7 +225,7 @@ std::string MeshGeometry::GetTextureCoordChannelName( unsigned int index ) const } const std::vector& MeshGeometry::GetVertexColors( unsigned int index ) const { - static const std::vector empty; + const std::vector empty; return index >= AI_MAX_NUMBER_OF_COLOR_SETS ? empty : m_colors[ index ]; } @@ -308,7 +306,6 @@ void MeshGeometry::ReadLayerElement(const Scope& layerElement) << type << ", index: " << typedIndex); } - // ------------------------------------------------------------------------------------------------ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scope& source) { @@ -412,7 +409,6 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop } } - // ------------------------------------------------------------------------------------------------ // Lengthy utility function to read and resolve a FBX vertex data array - that is, the // output is in polygon vertex order. This logic is used for reading normals, UVs, colors, @@ -431,7 +427,7 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, bool isDirect = ReferenceInformationType == "Direct"; bool isIndexToDirect = ReferenceInformationType == "IndexToDirect"; - // fallback to direct data if there is no index data element + // fall-back to direct data if there is no index data element if ( isIndexToDirect && !HasElement( source, indexDataElementName ) ) { isDirect = true; isIndexToDirect = false; @@ -499,9 +495,14 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, return; } + const T empty; unsigned int next = 0; for(int i : uvIndices) { - if (static_cast(i) >= tempData.size()) { + if ( -1 == i ) { + data_out[ next++ ] = empty; + continue; + } + if (static_cast(i) >= tempData.size()) { DOMError("index out of range",&GetRequiredElement(source,indexDataElementName)); } @@ -528,7 +529,6 @@ void MeshGeometry::ReadVertexDataNormals(std::vector& normals_out, c m_mappings); } - // ------------------------------------------------------------------------------------------------ void MeshGeometry::ReadVertexDataUV(std::vector& uv_out, const Scope& source, const std::string& MappingInformationType, @@ -543,7 +543,6 @@ void MeshGeometry::ReadVertexDataUV(std::vector& uv_out, const Scope m_mappings); } - // ------------------------------------------------------------------------------------------------ void MeshGeometry::ReadVertexDataColors(std::vector& colors_out, const Scope& source, const std::string& MappingInformationType, diff --git a/code/FBXMeshGeometry.h b/code/FBXMeshGeometry.h index 5dbf6f491..acd44668a 100644 --- a/code/FBXMeshGeometry.h +++ b/code/FBXMeshGeometry.h @@ -68,7 +68,6 @@ private: const Skin* skin; }; - typedef std::vector MatIndexArray; @@ -95,8 +94,8 @@ public: * if no tangents are specified */ const std::vector& GetTangents() const; - /** Get a list of all vertex binormals or an empty array - * if no binormals are specified */ + /** Get a list of all vertex bi-normals or an empty array + * if no bi-normals are specified */ const std::vector& GetBinormals() const; /** Return list of faces - each entry denotes a face and specifies diff --git a/include/assimp/IOStreamBuffer.h b/include/assimp/IOStreamBuffer.h index fdc339062..c93a191df 100644 --- a/include/assimp/IOStreamBuffer.h +++ b/include/assimp/IOStreamBuffer.h @@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include + #include "ParsingUtils.h" #include @@ -270,8 +271,8 @@ bool IOStreamBuffer::getNextDataLine( std::vector &buffer, T continuationT } buffer[ i ] = m_cache[ m_cachePos ]; - m_cachePos++; - i++; + ++m_cachePos; + ++i; if ( m_cachePos >= m_cacheSize ) { if ( !readNextBlock() ) { return false; @@ -280,13 +281,12 @@ bool IOStreamBuffer::getNextDataLine( std::vector &buffer, T continuationT } buffer[ i ] = '\n'; - m_cachePos++; + ++m_cachePos; return true; } -static -inline +static inline bool isEndOfCache( size_t pos, size_t cacheSize ) { return ( pos == cacheSize ); } @@ -314,11 +314,11 @@ bool IOStreamBuffer::getNextLine(std::vector &buffer) { } } - size_t i = 0; + size_t i( 0 ); while (!IsLineEnd(m_cache[ m_cachePos ])) { buffer[i] = m_cache[ m_cachePos ]; - m_cachePos++; - i++; + ++m_cachePos; + ++i; if (m_cachePos >= m_cacheSize) { if (!readNextBlock()) { return false; @@ -326,7 +326,7 @@ bool IOStreamBuffer::getNextLine(std::vector &buffer) { } } buffer[i] = '\n'; - m_cachePos++; + ++m_cachePos; return true; } @@ -334,18 +334,19 @@ bool IOStreamBuffer::getNextLine(std::vector &buffer) { template inline bool IOStreamBuffer::getNextBlock( std::vector &buffer) { - //just return the last blockvalue if getNextLine was used before - if ( m_cachePos != 0) { - buffer = std::vector(m_cache.begin() + m_cachePos, m_cache.end()); - m_cachePos = 0; - } - else { - if ( !readNextBlock() ) - return false; + // Return the last block-value if getNextLine was used before + if ( 0 != m_cachePos ) { + buffer = std::vector( m_cache.begin() + m_cachePos, m_cache.end() ); + m_cachePos = 0; + } else { + if ( !readNextBlock() ) { + return false; + } - buffer = std::vector(m_cache.begin(), m_cache.end()); - } - return true; + buffer = std::vector(m_cache.begin(), m_cache.end()); + } + + return true; } } // !ns Assimp From be4c7801152c3b54bb32eb7d4598a140b4efcd5f Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 22 Mar 2018 23:08:25 +0100 Subject: [PATCH 108/278] Update FBXMeshGeometry.cpp Fix build. --- code/FBXMeshGeometry.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/FBXMeshGeometry.cpp b/code/FBXMeshGeometry.cpp index 12001f76c..cc1a5a83e 100644 --- a/code/FBXMeshGeometry.cpp +++ b/code/FBXMeshGeometry.cpp @@ -216,7 +216,7 @@ const std::vector& MeshGeometry::GetFaceIndexCounts() const { // ------------------------------------------------------------------------------------------------ const std::vector& MeshGeometry::GetTextureCoords( unsigned int index ) const { - const std::vector empty; + static const std::vector empty; return index >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? empty : m_uvs[ index ]; } @@ -225,7 +225,7 @@ std::string MeshGeometry::GetTextureCoordChannelName( unsigned int index ) const } const std::vector& MeshGeometry::GetVertexColors( unsigned int index ) const { - const std::vector empty; + static const std::vector empty; return index >= AI_MAX_NUMBER_OF_COLOR_SETS ? empty : m_colors[ index ]; } From 15e9907340f98aa2ad39a56ae072fe0994a45215 Mon Sep 17 00:00:00 2001 From: Tommy Date: Mon, 26 Mar 2018 11:25:32 +0200 Subject: [PATCH 109/278] Address some gcc warnings about signed / unsigned comparison. --- test/unit/utMetadata.cpp | 2 +- test/unit/utPLYImportExport.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/unit/utMetadata.cpp b/test/unit/utMetadata.cpp index 42f632bce..0801ffd3f 100644 --- a/test/unit/utMetadata.cpp +++ b/test/unit/utMetadata.cpp @@ -199,7 +199,7 @@ TEST_F( utMetadata, copy_test ) { m_data->Set( 6, "aiVector3D", vecVal ); aiMetadata copy( *m_data ); - EXPECT_EQ( 7, copy.mNumProperties ); + EXPECT_EQ( 7u, copy.mNumProperties ); // bool test { diff --git a/test/unit/utPLYImportExport.cpp b/test/unit/utPLYImportExport.cpp index e0f96195b..c009bda39 100644 --- a/test/unit/utPLYImportExport.cpp +++ b/test/unit/utPLYImportExport.cpp @@ -132,10 +132,10 @@ TEST_F( utPLYImportExport, vertexColorTest ) { EXPECT_EQ(true, scene->mMeshes[0]->HasVertexColors(0)); auto first_face = scene->mMeshes[0]->mFaces[0]; - EXPECT_EQ(3, first_face.mNumIndices); - EXPECT_EQ(0, first_face.mIndices[0]); - EXPECT_EQ(1, first_face.mIndices[1]); - EXPECT_EQ(2, first_face.mIndices[2]); + EXPECT_EQ(3u, first_face.mNumIndices); + EXPECT_EQ(0u, first_face.mIndices[0]); + EXPECT_EQ(1u, first_face.mIndices[1]); + EXPECT_EQ(2u, first_face.mIndices[2]); } //Test issue #623, PLY importer should not automatically create faces From 2dff6e2d5b434d0d738693fadd189f5dcfc7859f Mon Sep 17 00:00:00 2001 From: Tommy Date: Mon, 26 Mar 2018 18:27:15 +0200 Subject: [PATCH 110/278] FBXExportProperty: implement float and long array properties. --- code/FBXExportProperty.cpp | 36 ++++++++++++++++++++++++++++++++++++ code/FBXExportProperty.h | 2 ++ 2 files changed, 38 insertions(+) diff --git a/code/FBXExportProperty.cpp b/code/FBXExportProperty.cpp index 975e9a09a..e139bb95a 100644 --- a/code/FBXExportProperty.cpp +++ b/code/FBXExportProperty.cpp @@ -116,6 +116,20 @@ FBX::Property::Property(const std::vector& va) for (size_t i = 0; i < va.size(); ++i) { d[i] = va[i]; } } +FBX::Property::Property(const std::vector& va) + : type('l'), data(8*va.size()) +{ + int64_t* d = reinterpret_cast(data.data()); + for (size_t i = 0; i < va.size(); ++i) { d[i] = va[i]; } +} + +FBX::Property::Property(const std::vector& va) + : type('f'), data(4*va.size()) +{ + float* d = reinterpret_cast(data.data()); + for (size_t i = 0; i < va.size(); ++i) { d[i] = va[i]; } +} + FBX::Property::Property(const std::vector& va) : type('d'), data(8*va.size()) { @@ -178,6 +192,28 @@ void FBX::Property::Dump(Assimp::StreamWriterLE &s) s.PutI4((reinterpret_cast(d))[i]); } return; + case 'l': + N = data.size() / 8; + s.PutU4(uint32_t(N)); // number of elements + s.PutU4(0); // no encoding (1 would be zip-compressed) + // TODO: compress if large? + s.PutU4(uint32_t(data.size())); // data size + d = data.data(); + for (size_t i = 0; i < N; ++i) { + s.PutI8((reinterpret_cast(d))[i]); + } + return; + case 'f': + N = data.size() / 4; + s.PutU4(uint32_t(N)); // number of elements + s.PutU4(0); // no encoding (1 would be zip-compressed) + // TODO: compress if large? + s.PutU4(uint32_t(data.size())); // data size + d = data.data(); + for (size_t i = 0; i < N; ++i) { + s.PutF4((reinterpret_cast(d))[i]); + } + return; case 'd': N = data.size() / 8; s.PutU4(uint32_t(N)); // number of elements diff --git a/code/FBXExportProperty.h b/code/FBXExportProperty.h index 8920346a3..40a020688 100644 --- a/code/FBXExportProperty.h +++ b/code/FBXExportProperty.h @@ -96,7 +96,9 @@ public: explicit Property(const std::string& s, bool raw=false); explicit Property(const std::vector& r); explicit Property(const std::vector& va); + explicit Property(const std::vector& va); explicit Property(const std::vector& va); + explicit Property(const std::vector& va); explicit Property(const aiMatrix4x4& vm); // this will catch any type not defined above, From 57bd1258394b58ada6ec1295d86c2d774db66fc6 Mon Sep 17 00:00:00 2001 From: Tommy Date: Mon, 26 Mar 2018 18:30:47 +0200 Subject: [PATCH 111/278] FBX Export: implement basic animation export. --- code/FBXExporter.cpp | 439 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 434 insertions(+), 5 deletions(-) diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index 9ba5c0333..2cb7e470a 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -525,8 +525,9 @@ void FBXExporter::WriteDefinitions () total_count += count; // AnimationStack / FbxAnimStack - // this seems to always be here in Maya exports - count = 0; + // this seems to always be here in Maya exports, + // but no harm seems to come of leaving it out. + count = mScene->mNumAnimations; if (count) { n = FBX::Node("ObjectType", Property("AnimationStack")); n.AddChild("Count", count); @@ -544,8 +545,11 @@ void FBXExporter::WriteDefinitions () } // AnimationLayer / FbxAnimLayer - // this seems to always be here in Maya exports - count = 0; + // this seems to always be here in Maya exports, + // but no harm seems to come of leaving it out. + // Assimp doesn't support animation layers, + // so there will be one per aiAnimation + count = mScene->mNumAnimations; if (count) { n = FBX::Node("ObjectType", Property("AnimationLayer")); n.AddChild("Count", count); @@ -821,7 +825,7 @@ void FBXExporter::WriteDefinitions () } // AnimationCurveNode / FbxAnimCurveNode - count = 0; + count = mScene->mNumAnimations * 3; if (count) { n = FBX::Node("ObjectType", Property("AnimationCurveNode")); n.AddChild("Count", count); @@ -834,6 +838,15 @@ void FBXExporter::WriteDefinitions () total_count += count; } + // AnimationCurve / FbxAnimCurve + count = mScene->mNumAnimations * 9; + if (count) { + n = FBX::Node("ObjectType", Property("AnimationCurve")); + n.AddChild("Count", count); + object_nodes.push_back(n); + total_count += count; + } + // Pose count = 0; for (size_t i = 0; i < mScene->mNumMeshes; ++i) { @@ -911,6 +924,12 @@ aiMatrix4x4 get_world_transform(const aiNode* node, const aiScene* scene) return transform; } +int64_t to_ktime(double ticks, const aiAnimation* anim) { + if (anim->mTicksPerSecond <= 0) { + return ticks * FBX::SECOND; + } + return (ticks / anim->mTicksPerSecond) * FBX::SECOND; +} void FBXExporter::WriteObjects () { @@ -1849,6 +1868,416 @@ void FBXExporter::WriteObjects () outstream, mScene->mRootNode, 0, limbnodes ); + // animations + // + // in FBX there are: + // * AnimationStack - corresponds to an aiAnimation + // * AnimationLayer - a combinable animation component + // * AnimationCurveNode - links the property to be animated + // * AnimationCurve - defines animation data for a single property value + // + // the CurveNode also provides the default value for a property, + // such as the X, Y, Z coordinates for animatable translation. + // + // the Curve only specifies values for one component of the property, + // so there will be a separate AnimationCurve for X, Y, and Z. + // + // Assimp has: + // * aiAnimation - basically corresponds to an AnimationStack + // * aiNodeAnim - defines all animation for one aiNode + // * aiVectorKey/aiQuatKey - define the keyframe data for T/R/S + // + // assimp has no equivalent for AnimationLayer, + // and these are flattened on FBX import. + // we can assume there will be one per AnimationStack. + // + // the aiNodeAnim contains all animation data for a single aiNode, + // which will correspond to three AnimationCurveNode's: + // one each for translation, rotation and scale. + // The data for each of these will be put in 9 AnimationCurve's, + // T.X, T.Y, T.Z, R.X, R.Y, R.Z, etc. + + // AnimationStack / aiAnimation + std::vector animation_stack_uids(mScene->mNumAnimations); + for (size_t ai = 0; ai < mScene->mNumAnimations; ++ai) { + int64_t animstack_uid = generate_uid(); + animation_stack_uids[ai] = animstack_uid; + const aiAnimation* anim = mScene->mAnimations[ai]; + + FBX::Node asnode("AnimationStack"); + std::string name = anim->mName.C_Str() + FBX::SEPARATOR + "AnimStack"; + asnode.AddProperties(animstack_uid, name, ""); + FBX::Node p("Properties70"); + p.AddP70time("LocalStart", 0); + p.AddP70time("LocalStop", 0); + p.AddP70time("ReferenceStart", 0); + p.AddP70time("ReferenceStop", 0); + asnode.AddChild(p); + + // this node absurdly always pretends it has children + asnode.Begin(outstream); + asnode.DumpProperties(outstream); + asnode.EndProperties(outstream); + asnode.DumpChildren(outstream); + asnode.End(outstream, true); + + // note: animation stacks are not connected to anything + } + + // AnimationLayer - one per aiAnimation + std::vector animation_layer_uids(mScene->mNumAnimations); + for (size_t ai = 0; ai < mScene->mNumAnimations; ++ai) { + int64_t animlayer_uid = generate_uid(); + animation_layer_uids[ai] = animlayer_uid; + FBX::Node alnode("AnimationLayer"); + alnode.AddProperties(animlayer_uid, FBX::SEPARATOR + "AnimLayer", ""); + + // this node absurdly always pretends it has children + alnode.Begin(outstream); + alnode.DumpProperties(outstream); + alnode.EndProperties(outstream); + alnode.DumpChildren(outstream); + alnode.End(outstream, true); + + // connect to the relevant animstack + FBX::Node c("C"); + c.AddProperties("OO", animlayer_uid, animation_stack_uids[ai]); + connections.push_back(c); // TODO: emplace_back + } + + // AnimCurveNode - three per aiNodeAnim + std::vector>> curve_node_uids; + for (size_t ai = 0; ai < mScene->mNumAnimations; ++ai) { + const aiAnimation* anim = mScene->mAnimations[ai]; + const int64_t layer_uid = animation_layer_uids[ai]; + std::vector> nodeanim_uids; + for (size_t nai = 0; nai < anim->mNumChannels; ++nai) { + const aiNodeAnim* na = anim->mChannels[nai]; + // get the corresponding aiNode + const aiNode* node = mScene->mRootNode->FindNode(na->mNodeName); + // and its transform + const aiMatrix4x4 node_xfm = get_world_transform(node, mScene); + aiVector3D T, R, S; + node_xfm.Decompose(S, R, T); + // generate uids for all AnimationCurveNode + std::array ids; + ids[0] = generate_uid(); // T + ids[1] = generate_uid(); // R + ids[2] = generate_uid(); // S + + // translation + FBX::Node t("AnimationCurveNode"); + t.AddProperties(ids[0], "T" + FBX::SEPARATOR + "AnimCurveNode", ""); + FBX::Node tp("Properties70"); + tp.AddP70numberA("d|X", T.x); + tp.AddP70numberA("d|Y", T.y); + tp.AddP70numberA("d|Z", T.z); + t.AddChild(tp); + t.Dump(outstream); + // connect to layer + FBX::Node tcl("C"); + tcl.AddProperties("OO", ids[0], layer_uid); + connections.push_back(tcl); // TODO: emplace_back + // connect to bone + FBX::Node tcb("C"); + tcb.AddProperties("OP", ids[0], node_uids[node], "Lcl Translation"); + connections.push_back(tcb); // TODO: emplace_back + + // rotation + FBX::Node r("AnimationCurveNode"); + r.AddProperties(ids[1], "R" + FBX::SEPARATOR + "AnimCurveNode", ""); + FBX::Node rp("Properties70"); + rp.AddP70numberA("d|X", DEG*R.x); + rp.AddP70numberA("d|Y", DEG*R.y); + rp.AddP70numberA("d|Z", DEG*R.z); + r.AddChild(rp); + r.Dump(outstream); + // connect to layer + FBX::Node rcl("C"); + rcl.AddProperties("OO", ids[1], layer_uid); + connections.push_back(rcl); // TODO: emplace_back + // connect to bone + FBX::Node rcb("C"); + rcb.AddProperties("OP", ids[1], node_uids[node], "Lcl Rotation"); + connections.push_back(rcb); // TODO: emplace_back + + // scale + FBX::Node s("AnimationCurveNode"); + s.AddProperties(ids[2], "S" + FBX::SEPARATOR + "AnimCurveNode", ""); + FBX::Node sp("Properties70"); + sp.AddP70numberA("d|X", S.x); + sp.AddP70numberA("d|Y", S.y); + sp.AddP70numberA("d|Z", S.z); + s.AddChild(sp); + s.Dump(outstream); + // connect to layer + FBX::Node scl("C"); + scl.AddProperties("OO", ids[2], layer_uid); + connections.push_back(scl); // TODO: emplace_back + // connect to bone + FBX::Node scb("C"); + scb.AddProperties("OP", ids[2], node_uids[node], "Lcl Scaling"); + connections.push_back(scb); // TODO: emplace_back + + nodeanim_uids.push_back(ids); + } + curve_node_uids.push_back(nodeanim_uids); + } + + // AnimCurve - defines actual keyframe data. + // there's a separate curve for every component of every vector, + // for example a transform curvenode will have separate X/Y/Z AnimCurve's + for (size_t ai = 0; ai < mScene->mNumAnimations; ++ai) { + const aiAnimation* anim = mScene->mAnimations[ai]; + for (size_t nai = 0; nai < anim->mNumChannels; ++nai) { + const aiNodeAnim* na = anim->mChannels[nai]; + // get the corresponding aiNode + const aiNode* node = mScene->mRootNode->FindNode(na->mNodeName); + // and its transform + const aiMatrix4x4 node_xfm = get_world_transform(node, mScene); + aiVector3D T, R, S; + node_xfm.Decompose(S, R, T); + const std::array& ids = curve_node_uids[ai][nai]; + + int64_t curve_uid; + std::vector times; + std::vector values; + + // TODO: compress code (it's a bit annoying) + + // translation x + FBX::Node tx("AnimationCurve"); + curve_uid = generate_uid(); + tx.AddProperties(curve_uid, FBX::SEPARATOR + "AnimCurve", ""); + tx.AddChild("Default", double(T.x)); // default value + tx.AddChild("KeyVer", int32_t(4009)); + times.clear(); + values.clear(); + for (size_t pki = 0; pki < na->mNumPositionKeys; ++pki) { + const aiVectorKey& k = na->mPositionKeys[pki]; + times.push_back(to_ktime(k.mTime, anim)); + values.push_back(k.mValue.x); + } + tx.AddChild("KeyTime", times); + tx.AddChild("KeyValueFloat", values); + // TODO: keyframe flags (STUB for now) + tx.AddChild("KeyAttrFlags", std::vector{0}); + tx.AddChild("KeyAttrDataFloat", std::vector{0,0,0,0}); + tx.AddChild("KeyAttrRefCount", std::vector{static_cast(times.size())}); + tx.Dump(outstream); + FBX::Node txc("C"); + txc.AddProperties("OP", curve_uid, ids[0], "d|X"); + connections.push_back(txc); // TODO: emplace_back + + // translation y + FBX::Node ty("AnimationCurve"); + curve_uid = generate_uid(); + ty.AddProperties(curve_uid, FBX::SEPARATOR + "AnimCurve", ""); + ty.AddChild("Default", double(T.y)); // default value + ty.AddChild("KeyVer", int32_t(4009)); + times.clear(); + values.clear(); + for (size_t pki = 0; pki < na->mNumPositionKeys; ++pki) { + const aiVectorKey& k = na->mPositionKeys[pki]; + times.push_back(to_ktime(k.mTime, anim)); + values.push_back(k.mValue.y); + } + ty.AddChild("KeyTime", times); + ty.AddChild("KeyValueFloat", values); + // TODO: keyframe flags (STUB for now) + ty.AddChild("KeyAttrFlags", std::vector{0}); + ty.AddChild("KeyAttrDataFloat", std::vector{0,0,0,0}); + ty.AddChild("KeyAttrRefCount", std::vector{static_cast(times.size())}); + ty.Dump(outstream); + FBX::Node tyc("C"); + tyc.AddProperties("OP", curve_uid, ids[0], "d|Y"); + connections.push_back(tyc); // TODO: emplace_back + + // translation z + FBX::Node tz("AnimationCurve"); + curve_uid = generate_uid(); + tz.AddProperties(curve_uid, FBX::SEPARATOR + "AnimCurve", ""); + tz.AddChild("Default", double(T.z)); // default value + tz.AddChild("KeyVer", int32_t(4009)); + times.clear(); + values.clear(); + for (size_t pki = 0; pki < na->mNumPositionKeys; ++pki) { + const aiVectorKey& k = na->mPositionKeys[pki]; + times.push_back(to_ktime(k.mTime, anim)); + values.push_back(k.mValue.z); + } + tz.AddChild("KeyTime", times); + tz.AddChild("KeyValueFloat", values); + // TODO: keyframe flags (STUB for now) + tz.AddChild("KeyAttrFlags", std::vector{0}); + tz.AddChild("KeyAttrDataFloat", std::vector{0,0,0,0}); + tz.AddChild("KeyAttrRefCount", std::vector{static_cast(times.size())}); + tz.Dump(outstream); + FBX::Node tzc("C"); + tzc.AddProperties("OP", curve_uid, ids[0], "d|Z"); + connections.push_back(tzc); // TODO: emplace_back + + // rotation x + FBX::Node rx("AnimationCurve"); + curve_uid = generate_uid(); + rx.AddProperties(curve_uid, FBX::SEPARATOR + "AnimCurve", ""); + rx.AddChild("Default", double(R.x)); // default value + rx.AddChild("KeyVer", int32_t(4009)); + times.clear(); + values.clear(); + for (size_t pki = 0; pki < na->mNumRotationKeys; ++pki) { + const aiQuatKey& k = na->mRotationKeys[pki]; + times.push_back(to_ktime(k.mTime, anim)); + // there must be a better way... + aiMatrix4x4 m(k.mValue.GetMatrix()); + aiVector3D qs, qr, qt; + m.Decompose(qs, qr, qt); + qr *= DEG; + values.push_back(qr.x); + } + rx.AddChild("KeyTime", times); + rx.AddChild("KeyValueFloat", values); + // TODO: keyframe flags (STUB for now) + rx.AddChild("KeyAttrFlags", std::vector{0}); + rx.AddChild("KeyAttrDataFloat", std::vector{0,0,0,0}); + rx.AddChild("KeyAttrRefCount", std::vector{static_cast(times.size())}); + rx.Dump(outstream); + FBX::Node rxc("C"); + rxc.AddProperties("OP", curve_uid, ids[1], "d|X"); + connections.push_back(rxc); // TODO: emplace_back + + // rotation y + FBX::Node ry("AnimationCurve"); + curve_uid = generate_uid(); + ry.AddProperties(curve_uid, FBX::SEPARATOR + "AnimCurve", ""); + ry.AddChild("Default", double(R.y)); // default value + ry.AddChild("KeyVer", int32_t(4009)); + times.clear(); + values.clear(); + for (size_t pki = 0; pki < na->mNumRotationKeys; ++pki) { + const aiQuatKey& k = na->mRotationKeys[pki]; + times.push_back(to_ktime(k.mTime, anim)); + // there must be a better way... + aiMatrix4x4 m(k.mValue.GetMatrix()); + aiVector3D qs, qr, qt; + m.Decompose(qs, qr, qt); + qr *= DEG; + values.push_back(qr.y); + } + ry.AddChild("KeyTime", times); + ry.AddChild("KeyValueFloat", values); + // TODO: keyframe flags (STUB for now) + ry.AddChild("KeyAttrFlags", std::vector{0}); + ry.AddChild("KeyAttrDataFloat", std::vector{0,0,0,0}); + ry.AddChild("KeyAttrRefCount", std::vector{static_cast(times.size())}); + ry.Dump(outstream); + FBX::Node ryc("C"); + ryc.AddProperties("OP", curve_uid, ids[1], "d|Y"); + connections.push_back(ryc); // TODO: emplace_back + + // rotation z + FBX::Node rz("AnimationCurve"); + curve_uid = generate_uid(); + rz.AddProperties(curve_uid, FBX::SEPARATOR + "AnimCurve", ""); + rz.AddChild("Default", double(R.z)); // default value + rz.AddChild("KeyVer", int32_t(4009)); + times.clear(); + values.clear(); + for (size_t pki = 0; pki < na->mNumRotationKeys; ++pki) { + const aiQuatKey& k = na->mRotationKeys[pki]; + times.push_back(to_ktime(k.mTime, anim)); + // there must be a better way... + aiMatrix4x4 m(k.mValue.GetMatrix()); + aiVector3D qs, qr, qt; + m.Decompose(qs, qr, qt); + qr *= DEG; + values.push_back(qr.z); + } + rz.AddChild("KeyTime", times); + rz.AddChild("KeyValueFloat", values); + // TODO: keyframe flags (STUB for now) + rz.AddChild("KeyAttrFlags", std::vector{0}); + rz.AddChild("KeyAttrDataFloat", std::vector{0,0,0,0}); + rz.AddChild("KeyAttrRefCount", std::vector{static_cast(times.size())}); + rz.Dump(outstream); + FBX::Node rzc("C"); + rzc.AddProperties("OP", curve_uid, ids[1], "d|Z"); + connections.push_back(rzc); // TODO: emplace_back + + // scale x + FBX::Node sx("AnimationCurve"); + curve_uid = generate_uid(); + sx.AddProperties(curve_uid, FBX::SEPARATOR + "AnimCurve", ""); + sx.AddChild("Default", double(S.x)); // default value + sx.AddChild("KeyVer", int32_t(4009)); + times.clear(); + values.clear(); + for (size_t pki = 0; pki < na->mNumScalingKeys; ++pki) { + const aiVectorKey& k = na->mScalingKeys[pki]; + times.push_back(to_ktime(k.mTime, anim)); + values.push_back(k.mValue.x); + } + sx.AddChild("KeyTime", times); + sx.AddChild("KeyValueFloat", values); + // TODO: keyframe flags (STUB for now) + sx.AddChild("KeyAttrFlags", std::vector{0}); + sx.AddChild("KeyAttrDataFloat", std::vector{0,0,0,0}); + sx.AddChild("KeyAttrRefCount", std::vector{static_cast(times.size())}); + sx.Dump(outstream); + FBX::Node sxc("C"); + sxc.AddProperties("OP", curve_uid, ids[2], "d|X"); + connections.push_back(sxc); // TODO: emplace_back + + // scale y + FBX::Node sy("AnimationCurve"); + curve_uid = generate_uid(); + sy.AddProperties(curve_uid, FBX::SEPARATOR + "AnimCurve", ""); + sy.AddChild("Default", double(S.y)); // default value + sy.AddChild("KeyVer", int32_t(4009)); + times.clear(); + values.clear(); + for (size_t pki = 0; pki < na->mNumScalingKeys; ++pki) { + const aiVectorKey& k = na->mScalingKeys[pki]; + times.push_back(to_ktime(k.mTime, anim)); + values.push_back(k.mValue.y); + } + sy.AddChild("KeyTime", times); + sy.AddChild("KeyValueFloat", values); + // TODO: keyframe flags (STUB for now) + sy.AddChild("KeyAttrFlags", std::vector{0}); + sy.AddChild("KeyAttrDataFloat", std::vector{0,0,0,0}); + sy.AddChild("KeyAttrRefCount", std::vector{static_cast(times.size())}); + sy.Dump(outstream); + FBX::Node syc("C"); + syc.AddProperties("OP", curve_uid, ids[2], "d|Y"); + connections.push_back(syc); // TODO: emplace_back + + // scale z + FBX::Node sz("AnimationCurve"); + curve_uid = generate_uid(); + sz.AddProperties(curve_uid, FBX::SEPARATOR + "AnimCurve", ""); + sz.AddChild("Default", double(S.z)); // default value + sz.AddChild("KeyVer", int32_t(4009)); + times.clear(); + values.clear(); + for (size_t pki = 0; pki < na->mNumScalingKeys; ++pki) { + const aiVectorKey& k = na->mScalingKeys[pki]; + times.push_back(to_ktime(k.mTime, anim)); + values.push_back(k.mValue.z); + } + sz.AddChild("KeyTime", times); + sz.AddChild("KeyValueFloat", values); + // TODO: keyframe flags (STUB for now) + sz.AddChild("KeyAttrFlags", std::vector{0}); + sz.AddChild("KeyAttrDataFloat", std::vector{0,0,0,0}); + sz.AddChild("KeyAttrRefCount", std::vector{static_cast(times.size())}); + sz.Dump(outstream); + FBX::Node szc("C"); + szc.AddProperties("OP", curve_uid, ids[2], "d|Z"); + connections.push_back(szc); // TODO: emplace_back + } + } + object_node.End(outstream, true); } From ee0cdb39544ba8459a9052eda526b0a2a0c16a63 Mon Sep 17 00:00:00 2001 From: Tommy Date: Tue, 27 Mar 2018 13:03:10 +0200 Subject: [PATCH 112/278] FBX Export: Tidy animation export code. --- code/FBXExporter.cpp | 388 +++++++++++++------------------------------ code/FBXExporter.h | 17 ++ 2 files changed, 129 insertions(+), 276 deletions(-) diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index 2cb7e470a..284076ef6 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -962,7 +962,7 @@ void FBXExporter::WriteObjects () std::vector vertex_indices; // map of vertex value to its index in the data vector std::map index_by_vertex_value; - int32_t index = 0; + int32_t index = 0; for (size_t vi = 0; vi < m->mNumVertices; ++vi) { aiVector3D vtx = m->mVertices[vi]; auto elem = index_by_vertex_value.find(vtx); @@ -1071,7 +1071,7 @@ void FBXExporter::WriteObjects () std::vector uv_data; std::vector uv_indices; std::map index_by_uv; - int32_t index = 0; + int32_t index = 0; for (size_t fi = 0; fi < m->mNumFaces; ++fi) { const aiFace &f = m->mFaces[fi]; for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) { @@ -1908,13 +1908,14 @@ void FBXExporter::WriteObjects () std::string name = anim->mName.C_Str() + FBX::SEPARATOR + "AnimStack"; asnode.AddProperties(animstack_uid, name, ""); FBX::Node p("Properties70"); - p.AddP70time("LocalStart", 0); - p.AddP70time("LocalStop", 0); + p.AddP70time("LocalStart", 0); // assimp doesn't store this + p.AddP70time("LocalStop", to_ktime(anim->mDuration, anim)); p.AddP70time("ReferenceStart", 0); - p.AddP70time("ReferenceStop", 0); + p.AddP70time("ReferenceStop", to_ktime(anim->mDuration, anim)); asnode.AddChild(p); // this node absurdly always pretends it has children + // (in this case it does, but just in case...) asnode.Begin(outstream); asnode.DumpProperties(outstream); asnode.EndProperties(outstream); @@ -1959,66 +1960,32 @@ void FBXExporter::WriteObjects () const aiMatrix4x4 node_xfm = get_world_transform(node, mScene); aiVector3D T, R, S; node_xfm.Decompose(S, R, T); - // generate uids for all AnimationCurveNode + + // AnimationCurveNode uids std::array ids; ids[0] = generate_uid(); // T ids[1] = generate_uid(); // R ids[2] = generate_uid(); // S // translation - FBX::Node t("AnimationCurveNode"); - t.AddProperties(ids[0], "T" + FBX::SEPARATOR + "AnimCurveNode", ""); - FBX::Node tp("Properties70"); - tp.AddP70numberA("d|X", T.x); - tp.AddP70numberA("d|Y", T.y); - tp.AddP70numberA("d|Z", T.z); - t.AddChild(tp); - t.Dump(outstream); - // connect to layer - FBX::Node tcl("C"); - tcl.AddProperties("OO", ids[0], layer_uid); - connections.push_back(tcl); // TODO: emplace_back - // connect to bone - FBX::Node tcb("C"); - tcb.AddProperties("OP", ids[0], node_uids[node], "Lcl Translation"); - connections.push_back(tcb); // TODO: emplace_back + WriteAnimationCurveNode(outstream, + ids[0], "T", T, "Lcl Translation", + layer_uid, node_uids[node] + ); // rotation - FBX::Node r("AnimationCurveNode"); - r.AddProperties(ids[1], "R" + FBX::SEPARATOR + "AnimCurveNode", ""); - FBX::Node rp("Properties70"); - rp.AddP70numberA("d|X", DEG*R.x); - rp.AddP70numberA("d|Y", DEG*R.y); - rp.AddP70numberA("d|Z", DEG*R.z); - r.AddChild(rp); - r.Dump(outstream); - // connect to layer - FBX::Node rcl("C"); - rcl.AddProperties("OO", ids[1], layer_uid); - connections.push_back(rcl); // TODO: emplace_back - // connect to bone - FBX::Node rcb("C"); - rcb.AddProperties("OP", ids[1], node_uids[node], "Lcl Rotation"); - connections.push_back(rcb); // TODO: emplace_back + WriteAnimationCurveNode(outstream, + ids[1], "R", R, "Lcl Rotation", + layer_uid, node_uids[node] + ); // scale - FBX::Node s("AnimationCurveNode"); - s.AddProperties(ids[2], "S" + FBX::SEPARATOR + "AnimCurveNode", ""); - FBX::Node sp("Properties70"); - sp.AddP70numberA("d|X", S.x); - sp.AddP70numberA("d|Y", S.y); - sp.AddP70numberA("d|Z", S.z); - s.AddChild(sp); - s.Dump(outstream); - // connect to layer - FBX::Node scl("C"); - scl.AddProperties("OO", ids[2], layer_uid); - connections.push_back(scl); // TODO: emplace_back - // connect to bone - FBX::Node scb("C"); - scb.AddProperties("OP", ids[2], node_uids[node], "Lcl Scaling"); - connections.push_back(scb); // TODO: emplace_back + WriteAnimationCurveNode(outstream, + ids[2], "S", S, "Lcl Scale", + layer_uid, node_uids[node] + ); + // store the uids for later use nodeanim_uids.push_back(ids); } curve_node_uids.push_back(nodeanim_uids); @@ -2039,242 +2006,52 @@ void FBXExporter::WriteObjects () node_xfm.Decompose(S, R, T); const std::array& ids = curve_node_uids[ai][nai]; - int64_t curve_uid; std::vector times; - std::vector values; + std::vector xval, yval, zval; - // TODO: compress code (it's a bit annoying) - - // translation x - FBX::Node tx("AnimationCurve"); - curve_uid = generate_uid(); - tx.AddProperties(curve_uid, FBX::SEPARATOR + "AnimCurve", ""); - tx.AddChild("Default", double(T.x)); // default value - tx.AddChild("KeyVer", int32_t(4009)); - times.clear(); - values.clear(); - for (size_t pki = 0; pki < na->mNumPositionKeys; ++pki) { - const aiVectorKey& k = na->mPositionKeys[pki]; + // position/translation + for (size_t ki = 0; ki < na->mNumPositionKeys; ++ki) { + const aiVectorKey& k = na->mPositionKeys[ki]; times.push_back(to_ktime(k.mTime, anim)); - values.push_back(k.mValue.x); + xval.push_back(k.mValue.x); + yval.push_back(k.mValue.y); + zval.push_back(k.mValue.z); } - tx.AddChild("KeyTime", times); - tx.AddChild("KeyValueFloat", values); - // TODO: keyframe flags (STUB for now) - tx.AddChild("KeyAttrFlags", std::vector{0}); - tx.AddChild("KeyAttrDataFloat", std::vector{0,0,0,0}); - tx.AddChild("KeyAttrRefCount", std::vector{static_cast(times.size())}); - tx.Dump(outstream); - FBX::Node txc("C"); - txc.AddProperties("OP", curve_uid, ids[0], "d|X"); - connections.push_back(txc); // TODO: emplace_back + // one curve each for X, Y, Z + WriteAnimationCurve(outstream, T.x, times, xval, ids[0], "d|X"); + WriteAnimationCurve(outstream, T.y, times, yval, ids[0], "d|Y"); + WriteAnimationCurve(outstream, T.z, times, zval, ids[0], "d|Z"); - // translation y - FBX::Node ty("AnimationCurve"); - curve_uid = generate_uid(); - ty.AddProperties(curve_uid, FBX::SEPARATOR + "AnimCurve", ""); - ty.AddChild("Default", double(T.y)); // default value - ty.AddChild("KeyVer", int32_t(4009)); - times.clear(); - values.clear(); - for (size_t pki = 0; pki < na->mNumPositionKeys; ++pki) { - const aiVectorKey& k = na->mPositionKeys[pki]; + // rotation + times.clear(); xval.clear(); yval.clear(); zval.clear(); + for (size_t ki = 0; ki < na->mNumRotationKeys; ++ki) { + const aiQuatKey& k = na->mRotationKeys[ki]; times.push_back(to_ktime(k.mTime, anim)); - values.push_back(k.mValue.y); - } - ty.AddChild("KeyTime", times); - ty.AddChild("KeyValueFloat", values); - // TODO: keyframe flags (STUB for now) - ty.AddChild("KeyAttrFlags", std::vector{0}); - ty.AddChild("KeyAttrDataFloat", std::vector{0,0,0,0}); - ty.AddChild("KeyAttrRefCount", std::vector{static_cast(times.size())}); - ty.Dump(outstream); - FBX::Node tyc("C"); - tyc.AddProperties("OP", curve_uid, ids[0], "d|Y"); - connections.push_back(tyc); // TODO: emplace_back - - // translation z - FBX::Node tz("AnimationCurve"); - curve_uid = generate_uid(); - tz.AddProperties(curve_uid, FBX::SEPARATOR + "AnimCurve", ""); - tz.AddChild("Default", double(T.z)); // default value - tz.AddChild("KeyVer", int32_t(4009)); - times.clear(); - values.clear(); - for (size_t pki = 0; pki < na->mNumPositionKeys; ++pki) { - const aiVectorKey& k = na->mPositionKeys[pki]; - times.push_back(to_ktime(k.mTime, anim)); - values.push_back(k.mValue.z); - } - tz.AddChild("KeyTime", times); - tz.AddChild("KeyValueFloat", values); - // TODO: keyframe flags (STUB for now) - tz.AddChild("KeyAttrFlags", std::vector{0}); - tz.AddChild("KeyAttrDataFloat", std::vector{0,0,0,0}); - tz.AddChild("KeyAttrRefCount", std::vector{static_cast(times.size())}); - tz.Dump(outstream); - FBX::Node tzc("C"); - tzc.AddProperties("OP", curve_uid, ids[0], "d|Z"); - connections.push_back(tzc); // TODO: emplace_back - - // rotation x - FBX::Node rx("AnimationCurve"); - curve_uid = generate_uid(); - rx.AddProperties(curve_uid, FBX::SEPARATOR + "AnimCurve", ""); - rx.AddChild("Default", double(R.x)); // default value - rx.AddChild("KeyVer", int32_t(4009)); - times.clear(); - values.clear(); - for (size_t pki = 0; pki < na->mNumRotationKeys; ++pki) { - const aiQuatKey& k = na->mRotationKeys[pki]; - times.push_back(to_ktime(k.mTime, anim)); - // there must be a better way... + // TODO: aiQuaternion method to convert to Euler... aiMatrix4x4 m(k.mValue.GetMatrix()); aiVector3D qs, qr, qt; m.Decompose(qs, qr, qt); qr *= DEG; - values.push_back(qr.x); + xval.push_back(qr.x); + yval.push_back(qr.y); + zval.push_back(qr.z); } - rx.AddChild("KeyTime", times); - rx.AddChild("KeyValueFloat", values); - // TODO: keyframe flags (STUB for now) - rx.AddChild("KeyAttrFlags", std::vector{0}); - rx.AddChild("KeyAttrDataFloat", std::vector{0,0,0,0}); - rx.AddChild("KeyAttrRefCount", std::vector{static_cast(times.size())}); - rx.Dump(outstream); - FBX::Node rxc("C"); - rxc.AddProperties("OP", curve_uid, ids[1], "d|X"); - connections.push_back(rxc); // TODO: emplace_back + WriteAnimationCurve(outstream, R.x, times, xval, ids[1], "d|X"); + WriteAnimationCurve(outstream, R.y, times, yval, ids[1], "d|Y"); + WriteAnimationCurve(outstream, R.z, times, zval, ids[1], "d|Z"); - // rotation y - FBX::Node ry("AnimationCurve"); - curve_uid = generate_uid(); - ry.AddProperties(curve_uid, FBX::SEPARATOR + "AnimCurve", ""); - ry.AddChild("Default", double(R.y)); // default value - ry.AddChild("KeyVer", int32_t(4009)); - times.clear(); - values.clear(); - for (size_t pki = 0; pki < na->mNumRotationKeys; ++pki) { - const aiQuatKey& k = na->mRotationKeys[pki]; + // scaling/scale + times.clear(); xval.clear(); yval.clear(); zval.clear(); + for (size_t ki = 0; ki < na->mNumScalingKeys; ++ki) { + const aiVectorKey& k = na->mScalingKeys[ki]; times.push_back(to_ktime(k.mTime, anim)); - // there must be a better way... - aiMatrix4x4 m(k.mValue.GetMatrix()); - aiVector3D qs, qr, qt; - m.Decompose(qs, qr, qt); - qr *= DEG; - values.push_back(qr.y); + xval.push_back(k.mValue.x); + yval.push_back(k.mValue.y); + zval.push_back(k.mValue.z); } - ry.AddChild("KeyTime", times); - ry.AddChild("KeyValueFloat", values); - // TODO: keyframe flags (STUB for now) - ry.AddChild("KeyAttrFlags", std::vector{0}); - ry.AddChild("KeyAttrDataFloat", std::vector{0,0,0,0}); - ry.AddChild("KeyAttrRefCount", std::vector{static_cast(times.size())}); - ry.Dump(outstream); - FBX::Node ryc("C"); - ryc.AddProperties("OP", curve_uid, ids[1], "d|Y"); - connections.push_back(ryc); // TODO: emplace_back - - // rotation z - FBX::Node rz("AnimationCurve"); - curve_uid = generate_uid(); - rz.AddProperties(curve_uid, FBX::SEPARATOR + "AnimCurve", ""); - rz.AddChild("Default", double(R.z)); // default value - rz.AddChild("KeyVer", int32_t(4009)); - times.clear(); - values.clear(); - for (size_t pki = 0; pki < na->mNumRotationKeys; ++pki) { - const aiQuatKey& k = na->mRotationKeys[pki]; - times.push_back(to_ktime(k.mTime, anim)); - // there must be a better way... - aiMatrix4x4 m(k.mValue.GetMatrix()); - aiVector3D qs, qr, qt; - m.Decompose(qs, qr, qt); - qr *= DEG; - values.push_back(qr.z); - } - rz.AddChild("KeyTime", times); - rz.AddChild("KeyValueFloat", values); - // TODO: keyframe flags (STUB for now) - rz.AddChild("KeyAttrFlags", std::vector{0}); - rz.AddChild("KeyAttrDataFloat", std::vector{0,0,0,0}); - rz.AddChild("KeyAttrRefCount", std::vector{static_cast(times.size())}); - rz.Dump(outstream); - FBX::Node rzc("C"); - rzc.AddProperties("OP", curve_uid, ids[1], "d|Z"); - connections.push_back(rzc); // TODO: emplace_back - - // scale x - FBX::Node sx("AnimationCurve"); - curve_uid = generate_uid(); - sx.AddProperties(curve_uid, FBX::SEPARATOR + "AnimCurve", ""); - sx.AddChild("Default", double(S.x)); // default value - sx.AddChild("KeyVer", int32_t(4009)); - times.clear(); - values.clear(); - for (size_t pki = 0; pki < na->mNumScalingKeys; ++pki) { - const aiVectorKey& k = na->mScalingKeys[pki]; - times.push_back(to_ktime(k.mTime, anim)); - values.push_back(k.mValue.x); - } - sx.AddChild("KeyTime", times); - sx.AddChild("KeyValueFloat", values); - // TODO: keyframe flags (STUB for now) - sx.AddChild("KeyAttrFlags", std::vector{0}); - sx.AddChild("KeyAttrDataFloat", std::vector{0,0,0,0}); - sx.AddChild("KeyAttrRefCount", std::vector{static_cast(times.size())}); - sx.Dump(outstream); - FBX::Node sxc("C"); - sxc.AddProperties("OP", curve_uid, ids[2], "d|X"); - connections.push_back(sxc); // TODO: emplace_back - - // scale y - FBX::Node sy("AnimationCurve"); - curve_uid = generate_uid(); - sy.AddProperties(curve_uid, FBX::SEPARATOR + "AnimCurve", ""); - sy.AddChild("Default", double(S.y)); // default value - sy.AddChild("KeyVer", int32_t(4009)); - times.clear(); - values.clear(); - for (size_t pki = 0; pki < na->mNumScalingKeys; ++pki) { - const aiVectorKey& k = na->mScalingKeys[pki]; - times.push_back(to_ktime(k.mTime, anim)); - values.push_back(k.mValue.y); - } - sy.AddChild("KeyTime", times); - sy.AddChild("KeyValueFloat", values); - // TODO: keyframe flags (STUB for now) - sy.AddChild("KeyAttrFlags", std::vector{0}); - sy.AddChild("KeyAttrDataFloat", std::vector{0,0,0,0}); - sy.AddChild("KeyAttrRefCount", std::vector{static_cast(times.size())}); - sy.Dump(outstream); - FBX::Node syc("C"); - syc.AddProperties("OP", curve_uid, ids[2], "d|Y"); - connections.push_back(syc); // TODO: emplace_back - - // scale z - FBX::Node sz("AnimationCurve"); - curve_uid = generate_uid(); - sz.AddProperties(curve_uid, FBX::SEPARATOR + "AnimCurve", ""); - sz.AddChild("Default", double(S.z)); // default value - sz.AddChild("KeyVer", int32_t(4009)); - times.clear(); - values.clear(); - for (size_t pki = 0; pki < na->mNumScalingKeys; ++pki) { - const aiVectorKey& k = na->mScalingKeys[pki]; - times.push_back(to_ktime(k.mTime, anim)); - values.push_back(k.mValue.z); - } - sz.AddChild("KeyTime", times); - sz.AddChild("KeyValueFloat", values); - // TODO: keyframe flags (STUB for now) - sz.AddChild("KeyAttrFlags", std::vector{0}); - sz.AddChild("KeyAttrDataFloat", std::vector{0,0,0,0}); - sz.AddChild("KeyAttrRefCount", std::vector{static_cast(times.size())}); - sz.Dump(outstream); - FBX::Node szc("C"); - szc.AddProperties("OP", curve_uid, ids[2], "d|Z"); - connections.push_back(szc); // TODO: emplace_back + WriteAnimationCurve(outstream, S.x, times, xval, ids[2], "d|X"); + WriteAnimationCurve(outstream, S.y, times, yval, ids[2], "d|Y"); + WriteAnimationCurve(outstream, S.z, times, zval, ids[2], "d|Z"); } } @@ -2548,6 +2325,65 @@ void FBXExporter::WriteModelNodes( } } + +void FBXExporter::WriteAnimationCurveNode( + StreamWriterLE& outstream, + int64_t uid, + std::string name, // "T", "R", or "S" + aiVector3D default_value, + std::string property_name, // "Lcl Translation" etc + int64_t layer_uid, + int64_t node_uid +) { + FBX::Node n("AnimationCurveNode"); + n.AddProperties(uid, name + FBX::SEPARATOR + "AnimCurveNode", ""); + FBX::Node p("Properties70"); + p.AddP70numberA("d|X", default_value.x); + p.AddP70numberA("d|Y", default_value.y); + p.AddP70numberA("d|Z", default_value.z); + n.AddChild(p); + n.Dump(outstream); + // connect to layer + FBX::Node cl("C"); + cl.AddProperties("OO", uid, layer_uid); + this->connections.push_back(cl); // TODO: emplace_back + // connect to bone + FBX::Node cb("C"); + cb.AddProperties("OP", uid, node_uid, property_name); + this->connections.push_back(cb); // TODO: emplace_back +} + + +void FBXExporter::WriteAnimationCurve( + StreamWriterLE& outstream, + double default_value, + const std::vector& times, + const std::vector& values, + int64_t curvenode_uid, + const std::string& property_link // "d|X", "d|Y", etc +) { + FBX::Node n("AnimationCurve"); + int64_t curve_uid = generate_uid(); + n.AddProperties(curve_uid, FBX::SEPARATOR + "AnimCurve", ""); + n.AddChild("Default", default_value); + n.AddChild("KeyVer", int32_t(4009)); + n.AddChild("KeyTime", times); + n.AddChild("KeyValueFloat", values); + // TODO: keyattr flags and data (STUB for now) + n.AddChild("KeyAttrFlags", std::vector{0}); + n.AddChild("KeyAttrDataFloat", std::vector{0,0,0,0}); + ai_assert(times.size() <= std::numeric_limits::max()); + n.AddChild( + "KeyAttrRefCount", + std::vector{static_cast(times.size())} + ); + n.Dump(outstream); + FBX::Node c("C"); + c.AddProperties("OP", curve_uid, curvenode_uid, property_link); + this->connections.push_back(c); // TODO: emplace_back +} + + void FBXExporter::WriteConnections () { // we should have completed the connection graph already, diff --git a/code/FBXExporter.h b/code/FBXExporter.h index ce2f67e24..553cf60fe 100644 --- a/code/FBXExporter.h +++ b/code/FBXExporter.h @@ -139,6 +139,23 @@ namespace Assimp const std::unordered_set& limbnodes, std::vector>& transform_chain ); + void WriteAnimationCurveNode( + StreamWriterLE& outstream, + int64_t uid, + std::string name, // "T", "R", or "S" + aiVector3D default_value, + std::string property_name, // "Lcl Translation" etc + int64_t animation_layer_uid, + int64_t node_uid + ); + void WriteAnimationCurve( + StreamWriterLE& outstream, + double default_value, + const std::vector& times, + const std::vector& values, + int64_t curvenode_id, + const std::string& property_link // "d|X", "d|Y", etc + ); }; } From e972b73fc21e3738f5ee928cf07b54f007a5d59b Mon Sep 17 00:00:00 2001 From: Tommy Date: Tue, 27 Mar 2018 13:29:03 +0200 Subject: [PATCH 113/278] FBX Export: tidy includes --- code/FBXExporter.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index 284076ef6..7dcf752da 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -63,6 +63,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include // localtime, tm_* #include #include +#include +#include #include #include // endl From 00277d93f2a56ace39fc3088b4c62308001ae192 Mon Sep 17 00:00:00 2001 From: Tommy Date: Wed, 28 Mar 2018 15:47:27 +0200 Subject: [PATCH 114/278] Tidier FBXExportNode construction with properties. --- code/FBXExportNode.h | 9 +-- code/FBXExporter.cpp | 136 +++++++++++++++++++------------------------ 2 files changed, 64 insertions(+), 81 deletions(-) diff --git a/code/FBXExportNode.h b/code/FBXExportNode.h index edce8f700..2539a9458 100644 --- a/code/FBXExportNode.h +++ b/code/FBXExportNode.h @@ -69,11 +69,12 @@ public: // public data members public: // constructors Node() = default; Node(const std::string& n) : name(n) {} - Node(const std::string& n, const FBX::Property &p) + + // convenience template to construct with properties directly + template + Node(const std::string& n, const More... more) : name(n) - { properties.push_back(p); } - Node(const std::string& n, const std::vector &pv) - : name(n), properties(pv) {} + { AddProperties(more...); } public: // functions to add properties or children // add a single property to the node diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index 7dcf752da..8b633462d 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -520,7 +520,7 @@ void FBXExporter::WriteDefinitions () // GlobalSettings // this seems to always be here in Maya exports - n = FBX::Node("ObjectType", Property("GlobalSettings")); + n = FBX::Node("ObjectType", "GlobalSettings"); count = 1; n.AddChild("Count", count); object_nodes.push_back(n); @@ -531,9 +531,9 @@ void FBXExporter::WriteDefinitions () // but no harm seems to come of leaving it out. count = mScene->mNumAnimations; if (count) { - n = FBX::Node("ObjectType", Property("AnimationStack")); + n = FBX::Node("ObjectType", "AnimationStack"); n.AddChild("Count", count); - pt = FBX::Node("PropertyTemplate", Property("FbxAnimStack")); + pt = FBX::Node("PropertyTemplate", "FbxAnimStack"); p = FBX::Node("Properties70"); p.AddP70string("Description", ""); p.AddP70time("LocalStart", 0); @@ -553,9 +553,9 @@ void FBXExporter::WriteDefinitions () // so there will be one per aiAnimation count = mScene->mNumAnimations; if (count) { - n = FBX::Node("ObjectType", Property("AnimationLayer")); + n = FBX::Node("ObjectType", "AnimationLayer"); n.AddChild("Count", count); - pt = FBX::Node("PropertyTemplate", Property("FBXAnimLayer")); + pt = FBX::Node("PropertyTemplate", "FBXAnimLayer"); p = FBX::Node("Properties70"); p.AddP70("Weight", "Number", "", "A", double(100)); p.AddP70bool("Mute", 0); @@ -583,9 +583,9 @@ void FBXExporter::WriteDefinitions () count = 1; // TODO: select properly if (count) { // FbxSkeleton - n = FBX::Node("ObjectType", Property("NodeAttribute")); + n = FBX::Node("ObjectType", "NodeAttribute"); n.AddChild("Count", count); - pt = FBX::Node("PropertyTemplate", Property("FbxSkeleton")); + pt = FBX::Node("PropertyTemplate", "FbxSkeleton"); p = FBX::Node("Properties70"); p.AddP70color("Color", 0.8, 0.8, 0.8); p.AddP70double("Size", 33.333333333333); @@ -601,9 +601,9 @@ void FBXExporter::WriteDefinitions () // <~~ node heirarchy count = int32_t(count_nodes(mScene->mRootNode)) - 1; // (not counting root node) if (count) { - n = FBX::Node("ObjectType", Property("Model")); + n = FBX::Node("ObjectType", "Model"); n.AddChild("Count", count); - pt = FBX::Node("PropertyTemplate", Property("FbxNode")); + pt = FBX::Node("PropertyTemplate", "FbxNode"); p = FBX::Node("Properties70"); p.AddP70enum("QuaternionInterpolate", 0); p.AddP70vector("RotationOffset", 0.0, 0.0, 0.0); @@ -698,9 +698,9 @@ void FBXExporter::WriteDefinitions () // <~~ aiMesh count = mScene->mNumMeshes; if (count) { - n = FBX::Node("ObjectType", Property("Geometry")); + n = FBX::Node("ObjectType", "Geometry"); n.AddChild("Count", count); - pt = FBX::Node("PropertyTemplate", Property("FbxMesh")); + pt = FBX::Node("PropertyTemplate", "FbxMesh"); p = FBX::Node("Properties70"); p.AddP70color("Color", 0, 0, 0); p.AddP70vector("BBoxMin", 0, 0, 0); @@ -724,7 +724,7 @@ void FBXExporter::WriteDefinitions () count = mScene->mNumMaterials; if (count) { bool has_phong = has_phong_mat(mScene); - n = FBX::Node("ObjectType", Property("Material")); + n = FBX::Node("ObjectType", "Material"); n.AddChild("Count", count); pt = FBX::Node("PropertyTemplate"); if (has_phong) { @@ -771,9 +771,9 @@ void FBXExporter::WriteDefinitions () // one for each image file. count = int32_t(count_images(mScene)); if (count) { - n = FBX::Node("ObjectType", Property("Video")); + n = FBX::Node("ObjectType", "Video"); n.AddChild("Count", count); - pt = FBX::Node("PropertyTemplate", Property("FbxVideo")); + pt = FBX::Node("PropertyTemplate", "FbxVideo"); p = FBX::Node("Properties70"); p.AddP70bool("ImageSequence", 0); p.AddP70int("ImageSequenceOffset", 0); @@ -800,9 +800,9 @@ void FBXExporter::WriteDefinitions () // <~~ aiTexture count = int32_t(count_textures(mScene)); if (count) { - n = FBX::Node("ObjectType", Property("Texture")); + n = FBX::Node("ObjectType", "Texture"); n.AddChild("Count", count); - pt = FBX::Node("PropertyTemplate", Property("FbxFileTexture")); + pt = FBX::Node("PropertyTemplate", "FbxFileTexture"); p = FBX::Node("Properties70"); p.AddP70enum("TextureTypeUse", 0); p.AddP70numberA("Texture alpha", 1.0); @@ -829,9 +829,9 @@ void FBXExporter::WriteDefinitions () // AnimationCurveNode / FbxAnimCurveNode count = mScene->mNumAnimations * 3; if (count) { - n = FBX::Node("ObjectType", Property("AnimationCurveNode")); + n = FBX::Node("ObjectType", "AnimationCurveNode"); n.AddChild("Count", count); - pt = FBX::Node("PropertyTemplate", Property("FbxAnimCurveNode")); + pt = FBX::Node("PropertyTemplate", "FbxAnimCurveNode"); p = FBX::Node("Properties70"); p.AddP70("d", "Compound", "", ""); pt.AddChild(p); @@ -843,7 +843,7 @@ void FBXExporter::WriteDefinitions () // AnimationCurve / FbxAnimCurve count = mScene->mNumAnimations * 9; if (count) { - n = FBX::Node("ObjectType", Property("AnimationCurve")); + n = FBX::Node("ObjectType", "AnimationCurve"); n.AddChild("Count", count); object_nodes.push_back(n); total_count += count; @@ -856,7 +856,7 @@ void FBXExporter::WriteDefinitions () if (mesh->HasBones()) { ++count; } } if (count) { - n = FBX::Node("ObjectType", Property("Pose")); + n = FBX::Node("ObjectType", "Pose"); n.AddChild("Count", count); object_nodes.push_back(n); total_count += count; @@ -865,7 +865,7 @@ void FBXExporter::WriteDefinitions () // Deformer count = int32_t(count_deformers(mScene)); if (count) { - n = FBX::Node("ObjectType", Property("Deformer")); + n = FBX::Node("ObjectType", "Deformer"); n.AddChild("Count", count); object_nodes.push_back(n); total_count += count; @@ -874,9 +874,9 @@ void FBXExporter::WriteDefinitions () // (template) count = 0; if (count) { - n = FBX::Node("ObjectType", Property("")); + n = FBX::Node("ObjectType", ""); n.AddChild("Count", count); - pt = FBX::Node("PropertyTemplate", Property("")); + pt = FBX::Node("PropertyTemplate", ""); p = FBX::Node("Properties70"); pt.AddChild(p); n.AddChild(pt); @@ -1008,7 +1008,7 @@ void FBXExporter::WriteObjects () // normals, if any if (m->HasNormals()) { - FBX::Node normals("LayerElementNormal", Property(int32_t(0))); + FBX::Node normals("LayerElementNormal", int32_t(0)); normals.Begin(outstream); normals.DumpProperties(outstream); normals.EndProperties(outstream); @@ -1055,7 +1055,7 @@ void FBXExporter::WriteObjects () err << " but may be incorrectly interpreted on load."; DefaultLogger::get()->warn(err.str()); } - FBX::Node uv("LayerElementUV", Property(int32_t(uvi))); + FBX::Node uv("LayerElementUV", int32_t(uvi)); uv.Begin(outstream); uv.DumpProperties(outstream); uv.EndProperties(outstream); @@ -1100,7 +1100,7 @@ void FBXExporter::WriteObjects () // i'm not really sure why this material section exists, // as the material is linked via "Connections". // it seems to always have the same "0" value. - FBX::Node mat("LayerElementMaterial", Property(int32_t(0))); + FBX::Node mat("LayerElementMaterial", int32_t(0)); mat.AddChild("Version", int32_t(101)); mat.AddChild("Name", ""); mat.AddChild("MappingInformationType", "AllSame"); @@ -1112,7 +1112,7 @@ void FBXExporter::WriteObjects () // finally we have the layer specifications, // which select the normals / UV set / etc to use. // TODO: handle multiple uv sets correctly? - FBX::Node layer("Layer", Property(int32_t(0))); + FBX::Node layer("Layer", int32_t(0)); layer.AddChild("Version", int32_t(100)); FBX::Node le("LayerElement"); le.AddChild("Type", "LayerElementNormal"); @@ -1408,14 +1408,12 @@ void FBXExporter::WriteObjects () const int64_t texture_uid = generate_uid(); // link the texture to the material - FBX::Node c("C"); - c.AddProperties("OP", texture_uid, material_uid, prop_name); - connections.push_back(c); + connections.emplace_back( + "C", "OP", texture_uid, material_uid, prop_name + ); // link the image data to the texture - c = FBX::Node("C"); - c.AddProperties("OO", image_uid, texture_uid); - connections.push_back(c); + connections.emplace_back("C", "OO", image_uid, texture_uid); // now write the actual texture node FBX::Node tnode("Texture"); @@ -1598,9 +1596,7 @@ void FBXExporter::WriteObjects () dnode.Dump(outstream); // connect it - FBX::Node c("C"); - c.AddProperties("OO", deformer_uid, mesh_uids[mi]); - connections.push_back(c); // TODO: emplace_back + connections.emplace_back("C", "OO", deformer_uid, mesh_uids[mi]); // we will be indexing by vertex... // but there might be a different number of "vertices" @@ -1744,14 +1740,14 @@ void FBXExporter::WriteObjects () sdnode.Dump(outstream); // lastly, connect to the parent deformer - c = FBX::Node("C"); - c.AddProperties("OO", subdeformer_uid, deformer_uid); - connections.push_back(c); // TODO: emplace_back + connections.emplace_back( + "C", "OO", subdeformer_uid, deformer_uid + ); // we also need to connect the limb node to the subdeformer. - c = FBX::Node("C"); - c.AddProperties("OO", node_uids[bone_node], subdeformer_uid); - connections.push_back(c); // TODO: emplace_back + connections.emplace_back( + "C", "OO", node_uids[bone_node], subdeformer_uid + ); } // if we cannot create a valid FBX file, simply die. @@ -1943,9 +1939,9 @@ void FBXExporter::WriteObjects () alnode.End(outstream, true); // connect to the relevant animstack - FBX::Node c("C"); - c.AddProperties("OO", animlayer_uid, animation_stack_uids[ai]); - connections.push_back(c); // TODO: emplace_back + connections.emplace_back( + "C", "OO", animlayer_uid, animation_stack_uids[ai] + ); } // AnimCurveNode - three per aiNodeAnim @@ -2240,9 +2236,7 @@ void FBXExporter::WriteModelNodes( node_uid = generate_uid(); node_uids[node] = node_uid; } - FBX::Node c("C"); - c.AddProperties("OO", node_uid, parent_uid); - connections.push_back(c); + connections.emplace_back("C", "OO", node_uid, parent_uid); } // what type of node is this? @@ -2250,17 +2244,15 @@ void FBXExporter::WriteModelNodes( // handled later } else if (node->mNumMeshes == 1) { // connect to child mesh, which should have been written previously - FBX::Node c("C"); - c.AddProperties("OO", mesh_uids[node->mMeshes[0]], node_uid); - connections.push_back(c); + connections.emplace_back( + "C", "OO", mesh_uids[node->mMeshes[0]], node_uid + ); // also connect to the material for the child mesh - c = FBX::Node("C"); - c.AddProperties( - "OO", + connections.emplace_back( + "C", "OO", material_uids[mScene->mMeshes[node->mMeshes[0]]->mMaterialIndex], node_uid ); - connections.push_back(c); // write model node WriteModelNode(outstream, node, node_uid, "Mesh", transform_chain); } else if (limbnodes.count(node)) { @@ -2274,9 +2266,7 @@ void FBXExporter::WriteModelNodes( na.AddChild("TypeFlags", Property("Skeleton")); na.Dump(outstream); // and connect them - FBX::Node c("C"); - c.AddProperties("OO", node_attribute_uid, node_uid); - connections.push_back(c); + connections.emplace_back("C", "OO", node_attribute_uid, node_uid); } else { // generate a null node so we can add children to it WriteModelNode(outstream, node, node_uid, "Null", transform_chain); @@ -2288,23 +2278,19 @@ void FBXExporter::WriteModelNodes( // make a new model node int64_t new_node_uid = generate_uid(); // connect to parent node - FBX::Node c("C"); - c.AddProperties("OO", new_node_uid, node_uid); - connections.push_back(c); + connections.emplace_back("C", "OO", new_node_uid, node_uid); // connect to child mesh, which should have been written previously - c = FBX::Node("C"); - c.AddProperties("OO", mesh_uids[node->mMeshes[i]], new_node_uid); - connections.push_back(c); + connections.emplace_back( + "C", "OO", mesh_uids[node->mMeshes[i]], new_node_uid + ); // also connect to the material for the child mesh - c = FBX::Node("C"); - c.AddProperties( - "OO", + connections.emplace_back( + "C", "OO", material_uids[ mScene->mMeshes[node->mMeshes[i]]->mMaterialIndex ], new_node_uid ); - connections.push_back(c); // write model node FBX::Node m("Model"); // take name from mesh name, if it exists @@ -2346,13 +2332,9 @@ void FBXExporter::WriteAnimationCurveNode( n.AddChild(p); n.Dump(outstream); // connect to layer - FBX::Node cl("C"); - cl.AddProperties("OO", uid, layer_uid); - this->connections.push_back(cl); // TODO: emplace_back + this->connections.emplace_back("C", "OO", uid, layer_uid); // connect to bone - FBX::Node cb("C"); - cb.AddProperties("OP", uid, node_uid, property_name); - this->connections.push_back(cb); // TODO: emplace_back + this->connections.emplace_back("C", "OP", uid, node_uid, property_name); } @@ -2380,9 +2362,9 @@ void FBXExporter::WriteAnimationCurve( std::vector{static_cast(times.size())} ); n.Dump(outstream); - FBX::Node c("C"); - c.AddProperties("OP", curve_uid, curvenode_uid, property_link); - this->connections.push_back(c); // TODO: emplace_back + this->connections.emplace_back( + "C", "OP", curve_uid, curvenode_uid, property_link + ); } From aadb413fc07dccb8fe5b8fee8704b941f5713816 Mon Sep 17 00:00:00 2001 From: Tommy Date: Wed, 28 Mar 2018 16:09:07 +0200 Subject: [PATCH 115/278] Explicit handling of an FBXExportNode edge-case. --- code/FBXExportNode.cpp | 2 +- code/FBXExportNode.h | 3 +++ code/FBXExporter.cpp | 15 +++++---------- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/code/FBXExportNode.cpp b/code/FBXExportNode.cpp index 596901989..621e72f09 100644 --- a/code/FBXExportNode.cpp +++ b/code/FBXExportNode.cpp @@ -168,7 +168,7 @@ void FBX::Node::Dump(Assimp::StreamWriterLE &s) DumpChildren(s); // finish, filling in end offset placeholder - End(s, !children.empty()); + End(s, force_has_children || !children.empty()); } void FBX::Node::Begin(Assimp::StreamWriterLE &s) diff --git a/code/FBXExportNode.h b/code/FBXExportNode.h index 2539a9458..58d3d14ee 100644 --- a/code/FBXExportNode.h +++ b/code/FBXExportNode.h @@ -66,6 +66,9 @@ public: // public data members std::vector properties; // node properties std::vector children; // child nodes + // some nodes always pretend they have children... + bool force_has_children = false; + public: // constructors Node() = default; Node(const std::string& n) : name(n) {} diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index 8b633462d..46782cc2e 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -419,6 +419,7 @@ void FBXExporter::WriteReferences () // always empty for now. // not really sure what this is for. FBX::Node n("References"); + n.force_has_children = true; n.Dump(outfile); } @@ -1914,11 +1915,8 @@ void FBXExporter::WriteObjects () // this node absurdly always pretends it has children // (in this case it does, but just in case...) - asnode.Begin(outstream); - asnode.DumpProperties(outstream); - asnode.EndProperties(outstream); - asnode.DumpChildren(outstream); - asnode.End(outstream, true); + asnode.force_has_children = true; + asnode.Dump(outstream); // note: animation stacks are not connected to anything } @@ -1932,11 +1930,8 @@ void FBXExporter::WriteObjects () alnode.AddProperties(animlayer_uid, FBX::SEPARATOR + "AnimLayer", ""); // this node absurdly always pretends it has children - alnode.Begin(outstream); - alnode.DumpProperties(outstream); - alnode.EndProperties(outstream); - alnode.DumpChildren(outstream); - alnode.End(outstream, true); + alnode.force_has_children = true; + alnode.Dump(outstream); // connect to the relevant animstack connections.emplace_back( From e549705af0aa53a611a7739aa5567b392e4bea63 Mon Sep 17 00:00:00 2001 From: Tommy Date: Wed, 28 Mar 2018 21:38:22 +0200 Subject: [PATCH 116/278] StreamWriter: add a PutChar method to write a single char. --- include/assimp/StreamWriter.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/assimp/StreamWriter.h b/include/assimp/StreamWriter.h index 6f492df90..5ce3b172b 100644 --- a/include/assimp/StreamWriter.h +++ b/include/assimp/StreamWriter.h @@ -203,6 +203,12 @@ public: Put(n); } + // --------------------------------------------------------------------- + /** Write a single character to the stream */ + void PutChar(char c) { + Put(c); + } + // --------------------------------------------------------------------- /** Write an aiString to the stream */ void PutString(const aiString& s) From 826243f289cb4cdbc1c5e79dc8593ce6805a5f49 Mon Sep 17 00:00:00 2001 From: Tommy Date: Wed, 28 Mar 2018 21:40:26 +0200 Subject: [PATCH 117/278] Implement ascii FBX export. It's available under the 'fbxa' format id. --- code/Exporter.cpp | 4 +- code/FBXExportNode.cpp | 376 ++++++++++++++++++++++++++++++++----- code/FBXExportNode.h | 81 ++++++-- code/FBXExportProperty.cpp | 155 +++++++++++++-- code/FBXExportProperty.h | 6 +- code/FBXExporter.cpp | 275 ++++++++++++++++++--------- code/FBXExporter.h | 14 ++ 7 files changed, 747 insertions(+), 164 deletions(-) diff --git a/code/Exporter.cpp b/code/Exporter.cpp index 49523e658..b7478c0be 100644 --- a/code/Exporter.cpp +++ b/code/Exporter.cpp @@ -98,7 +98,7 @@ void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportPrope void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneFBX(const char*, IOSystem*, const aiScene*, const ExportProperties*); -//void ExportSceneFBXA(const char*, IOSystem*, const aiScene*, const ExportProperties*); +void ExportSceneFBXA(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportScene3MF( const char*, IOSystem*, const aiScene*, const ExportProperties* ); // ------------------------------------------------------------------------------------------------ @@ -173,7 +173,7 @@ Exporter::ExportFormatEntry gExporters[] = #ifndef ASSIMP_BUILD_NO_FBX_EXPORTER Exporter::ExportFormatEntry( "fbx", "Autodesk FBX (binary)", "fbx", &ExportSceneFBX, 0 ), - //Exporter::ExportFormatEntry( "fbxa", "Autodesk FBX (ascii)", "fbx", &ExportSceneFBXA, 0 ), + Exporter::ExportFormatEntry( "fbxa", "Autodesk FBX (ascii)", "fbx", &ExportSceneFBXA, 0 ), #endif #ifndef ASSIMP_BUILD_NO_3MF_EXPORTER diff --git a/code/FBXExportNode.cpp b/code/FBXExportNode.cpp index 621e72f09..514d5f360 100644 --- a/code/FBXExportNode.cpp +++ b/code/FBXExportNode.cpp @@ -45,10 +45,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXCommon.h" #include // StreamWriterLE +#include // DeadlyExportError #include #include +#include +#include // ostringstream #include // shared_ptr +#include // snprintf // AddP70 helpers... there's no usable pattern here, // so all are defined as separate functions. @@ -145,33 +149,174 @@ void FBX::Node::AddP70time( } +// public member functions for writing nodes to stream + +void FBX::Node::Dump( + std::shared_ptr outfile, + bool binary, int indent +) { + if (binary) { + Assimp::StreamWriterLE outstream(outfile); + DumpBinary(outstream); + } else { + std::ostringstream ss; + DumpAscii(ss, indent); + std::string s = ss.str(); + outfile->Write(s.c_str(), s.size(), 1); + } +} + +void FBX::Node::Dump( + Assimp::StreamWriterLE &outstream, + bool binary, int indent +) { + if (binary) { + DumpBinary(outstream); + } else { + std::ostringstream ss; + DumpAscii(ss, indent); + outstream.PutString(ss.str()); + } +} + + +// public member functions for low-level writing + +void FBX::Node::Begin( + Assimp::StreamWriterLE &s, + bool binary, int indent +) { + if (binary) { + BeginBinary(s); + } else { + // assume we're at the correct place to start already + (void)indent; + std::ostringstream ss; + BeginAscii(ss, indent); + s.PutString(ss.str()); + } +} + +void FBX::Node::DumpProperties( + Assimp::StreamWriterLE& s, + bool binary, int indent +) { + if (binary) { + DumpPropertiesBinary(s); + } else { + std::ostringstream ss; + DumpPropertiesAscii(ss, indent); + s.PutString(ss.str()); + } +} + +void FBX::Node::EndProperties( + Assimp::StreamWriterLE &s, + bool binary, int indent +) { + EndProperties(s, binary, indent, properties.size()); +} + +void FBX::Node::EndProperties( + Assimp::StreamWriterLE &s, + bool binary, int indent, + size_t num_properties +) { + if (binary) { + EndPropertiesBinary(s, num_properties); + } else { + // nothing to do + (void)indent; + } +} + +void FBX::Node::BeginChildren( + Assimp::StreamWriterLE &s, + bool binary, int indent +) { + if (binary) { + // nothing to do + } else { + std::ostringstream ss; + BeginChildrenAscii(ss, indent); + s.PutString(ss.str()); + } +} + +void FBX::Node::DumpChildren( + Assimp::StreamWriterLE& s, + bool binary, int indent +) { + if (binary) { + DumpChildrenBinary(s); + } else { + std::ostringstream ss; + DumpChildrenAscii(ss, indent); + s.PutString(ss.str()); + } +} + +void FBX::Node::End( + Assimp::StreamWriterLE &s, + bool binary, int indent, + bool has_children +) { + if (binary) { + EndBinary(s, has_children); + } else { + std::ostringstream ss; + EndAscii(ss, indent, has_children); + s.PutString(ss.str()); + } +} + + // public member functions for writing to binary fbx -void FBX::Node::Dump(std::shared_ptr outfile) -{ - Assimp::StreamWriterLE outstream(outfile); - Dump(outstream); -} - -void FBX::Node::Dump(Assimp::StreamWriterLE &s) +void FBX::Node::DumpBinary(Assimp::StreamWriterLE &s) { // write header section (with placeholders for some things) - Begin(s); + BeginBinary(s); // write properties - DumpProperties(s); + DumpPropertiesBinary(s); // go back and fill in property related placeholders - EndProperties(s, properties.size()); + EndPropertiesBinary(s, properties.size()); // write children - DumpChildren(s); + DumpChildrenBinary(s); // finish, filling in end offset placeholder - End(s, force_has_children || !children.empty()); + EndBinary(s, force_has_children || !children.empty()); } -void FBX::Node::Begin(Assimp::StreamWriterLE &s) + +// public member functions for writing to ascii fbx + +void FBX::Node::DumpAscii(std::ostream &s, int indent) +{ + // write name + BeginAscii(s, indent); + + // write properties + DumpPropertiesAscii(s, indent); + + if (force_has_children || !children.empty()) { + // begin children (with a '{') + BeginChildrenAscii(s, indent + 1); + // write children + DumpChildrenAscii(s, indent + 1); + } + + // finish (also closing the children bracket '}') + EndAscii(s, indent, force_has_children || !children.empty()); +} + + +// private member functions for low-level writing to fbx + +void FBX::Node::BeginBinary(Assimp::StreamWriterLE &s) { // remember start pos so we can come back and write the end pos this->start_pos = s.Tell(); @@ -189,26 +334,14 @@ void FBX::Node::Begin(Assimp::StreamWriterLE &s) this->property_start = s.Tell(); } -void FBX::Node::DumpProperties(Assimp::StreamWriterLE& s) +void FBX::Node::DumpPropertiesBinary(Assimp::StreamWriterLE& s) { for (auto &p : properties) { - p.Dump(s); + p.DumpBinary(s); } } -void FBX::Node::DumpChildren(Assimp::StreamWriterLE& s) -{ - for (FBX::Node& child : children) { - child.Dump(s); - } -} - -void FBX::Node::EndProperties(Assimp::StreamWriterLE &s) -{ - EndProperties(s, properties.size()); -} - -void FBX::Node::EndProperties( +void FBX::Node::EndPropertiesBinary( Assimp::StreamWriterLE &s, size_t num_properties ) { @@ -222,7 +355,14 @@ void FBX::Node::EndProperties( s.Seek(pos); } -void FBX::Node::End( +void FBX::Node::DumpChildrenBinary(Assimp::StreamWriterLE& s) +{ + for (FBX::Node& child : children) { + child.DumpBinary(s); + } +} + +void FBX::Node::EndBinary( Assimp::StreamWriterLE &s, bool has_children ) { @@ -237,48 +377,192 @@ void FBX::Node::End( } -// static member functions +void FBX::Node::BeginAscii(std::ostream& s, int indent) +{ + s << '\n'; + for (int i = 0; i < indent; ++i) { s << '\t'; } + s << name << ": "; +} -// convenience function to create and write a property node, -// holding a single property which is an array of values. -// does not copy the data, so is efficient for large arrays. +void FBX::Node::DumpPropertiesAscii(std::ostream &s, int indent) +{ + for (size_t i = 0; i < properties.size(); ++i) { + if (i > 0) { s << ", "; } + properties[i].DumpAscii(s, indent); + } +} + +void FBX::Node::BeginChildrenAscii(std::ostream& s, int indent) +{ + // only call this if there are actually children + s << " {"; + (void)indent; +} + +void FBX::Node::DumpChildrenAscii(std::ostream& s, int indent) +{ + // children will need a lot of padding and corralling + if (children.size() || force_has_children) { + for (size_t i = 0; i < children.size(); ++i) { + // no compression in ascii files, so skip this node if it exists + if (children[i].name == "EncryptionType") { continue; } + // the child can dump itself + children[i].DumpAscii(s, indent); + } + } +} + +void FBX::Node::EndAscii(std::ostream& s, int indent, bool has_children) +{ + if (!has_children) { return; } // nothing to do + s << '\n'; + for (int i = 0; i < indent; ++i) { s << '\t'; } + s << "}"; +} + +// private helpers for static member functions + +// ascii property node from vector of doubles +void FBX::Node::WritePropertyNodeAscii( + const std::string& name, + const std::vector& v, + Assimp::StreamWriterLE& s, + int indent +){ + char buffer[32]; + FBX::Node node(name); + node.Begin(s, false, indent); + std::string vsize = std::to_string(v.size()); + // * { + s.PutChar('*'); s.PutString(vsize); s.PutString(" {\n"); + // indent + 1 + for (int i = 0; i < indent + 1; ++i) { s.PutChar('\t'); } + // a: value,value,value,... + s.PutString("a: "); + int count = 0; + for (size_t i = 0; i < v.size(); ++i) { + if (i > 0) { s.PutChar(','); } + int len = snprintf(buffer, sizeof(buffer), "%f", v[i]); + count += len; + if (count > 2048) { s.PutChar('\n'); count = 0; } + if (len < 0 || len > 31) { + // this should never happen + throw DeadlyExportError("failed to convert double to string"); + } + for (int j = 0; j < len; ++j) { s.PutChar(buffer[j]); } + } + // } + s.PutChar('\n'); + for (int i = 0; i < indent; ++i) { s.PutChar('\t'); } + s.PutChar('}'); s.PutChar(' '); + node.End(s, false, indent, false); +} + +// ascii property node from vector of int32_t +void FBX::Node::WritePropertyNodeAscii( + const std::string& name, + const std::vector& v, + Assimp::StreamWriterLE& s, + int indent +){ + char buffer[32]; + FBX::Node node(name); + node.Begin(s, false, indent); + std::string vsize = std::to_string(v.size()); + // * { + s.PutChar('*'); s.PutString(vsize); s.PutString(" {\n"); + // indent + 1 + for (int i = 0; i < indent + 1; ++i) { s.PutChar('\t'); } + // a: value,value,value,... + s.PutString("a: "); + int count = 0; + for (size_t i = 0; i < v.size(); ++i) { + if (i > 0) { s.PutChar(','); } + int len = snprintf(buffer, sizeof(buffer), "%d", v[i]); + count += len; + if (count > 2048) { s.PutChar('\n'); count = 0; } + if (len < 0 || len > 31) { + // this should never happen + throw DeadlyExportError("failed to convert double to string"); + } + for (int j = 0; j < len; ++j) { s.PutChar(buffer[j]); } + } + // } + s.PutChar('\n'); + for (int i = 0; i < indent; ++i) { s.PutChar('\t'); } + s.PutChar('}'); s.PutChar(' '); + node.End(s, false, indent, false); +} + +// binary property node from vector of doubles // TODO: optional zip compression! -void FBX::Node::WritePropertyNode( +void FBX::Node::WritePropertyNodeBinary( const std::string& name, const std::vector& v, Assimp::StreamWriterLE& s ){ - Node node(name); - node.Begin(s); + FBX::Node node(name); + node.BeginBinary(s); s.PutU1('d'); s.PutU4(uint32_t(v.size())); // number of elements s.PutU4(0); // no encoding (1 would be zip-compressed) s.PutU4(uint32_t(v.size()) * 8); // data size for (auto it = v.begin(); it != v.end(); ++it) { s.PutF8(*it); } - node.EndProperties(s, 1); - node.End(s, false); + node.EndPropertiesBinary(s, 1); + node.EndBinary(s, false); } -// convenience function to create and write a property node, -// holding a single property which is an array of values. -// does not copy the data, so is efficient for large arrays. +// binary property node from vector of int32_t // TODO: optional zip compression! -void FBX::Node::WritePropertyNode( +void FBX::Node::WritePropertyNodeBinary( const std::string& name, const std::vector& v, Assimp::StreamWriterLE& s ){ - Node node(name); - node.Begin(s); + FBX::Node node(name); + node.BeginBinary(s); s.PutU1('i'); s.PutU4(uint32_t(v.size())); // number of elements s.PutU4(0); // no encoding (1 would be zip-compressed) s.PutU4(uint32_t(v.size()) * 4); // data size for (auto it = v.begin(); it != v.end(); ++it) { s.PutI4(*it); } - node.EndProperties(s, 1); - node.End(s, false); + node.EndPropertiesBinary(s, 1); + node.EndBinary(s, false); } +// public static member functions + +// convenience function to create and write a property node, +// holding a single property which is an array of values. +// does not copy the data, so is efficient for large arrays. +void FBX::Node::WritePropertyNode( + const std::string& name, + const std::vector& v, + Assimp::StreamWriterLE& s, + bool binary, int indent +){ + if (binary) { + FBX::Node::WritePropertyNodeBinary(name, v, s); + } else { + FBX::Node::WritePropertyNodeAscii(name, v, s, indent); + } +} + +// convenience function to create and write a property node, +// holding a single property which is an array of values. +// does not copy the data, so is efficient for large arrays. +void FBX::Node::WritePropertyNode( + const std::string& name, + const std::vector& v, + Assimp::StreamWriterLE& s, + bool binary, int indent +){ + if (binary) { + FBX::Node::WritePropertyNodeBinary(name, v, s); + } else { + FBX::Node::WritePropertyNodeAscii(name, v, s, indent); + } +} #endif // ASSIMP_BUILD_NO_FBX_EXPORTER #endif // ASSIMP_BUILD_NO_EXPORT diff --git a/code/FBXExportNode.h b/code/FBXExportNode.h index 58d3d14ee..5ddd8c77b 100644 --- a/code/FBXExportNode.h +++ b/code/FBXExportNode.h @@ -142,19 +142,48 @@ public: // support specifically for dealing with Properties70 nodes public: // member functions for writing data to a file or stream - // write the full node as binary data to the given file or stream - void Dump(std::shared_ptr outfile); - void Dump(Assimp::StreamWriterLE &s); + // write the full node to the given file or stream + void Dump( + std::shared_ptr outfile, + bool binary, int indent + ); + void Dump(Assimp::StreamWriterLE &s, bool binary, int indent); // these other functions are for writing data piece by piece. // they must be used carefully. // for usage examples see FBXExporter.cpp. - void Begin(Assimp::StreamWriterLE &s); - void DumpProperties(Assimp::StreamWriterLE& s); - void EndProperties(Assimp::StreamWriterLE &s); - void EndProperties(Assimp::StreamWriterLE &s, size_t num_properties); - void DumpChildren(Assimp::StreamWriterLE& s); - void End(Assimp::StreamWriterLE &s, bool has_children); + void Begin(Assimp::StreamWriterLE &s, bool binary, int indent); + void DumpProperties(Assimp::StreamWriterLE& s, bool binary, int indent); + void EndProperties(Assimp::StreamWriterLE &s, bool binary, int indent); + void EndProperties( + Assimp::StreamWriterLE &s, bool binary, int indent, + size_t num_properties + ); + void BeginChildren(Assimp::StreamWriterLE &s, bool binary, int indent); + void DumpChildren(Assimp::StreamWriterLE& s, bool binary, int indent); + void End( + Assimp::StreamWriterLE &s, bool binary, int indent, + bool has_children + ); + +private: // internal functions used for writing + + void DumpBinary(Assimp::StreamWriterLE &s); + void DumpAscii(Assimp::StreamWriterLE &s, int indent); + void DumpAscii(std::ostream &s, int indent); + + void BeginBinary(Assimp::StreamWriterLE &s); + void DumpPropertiesBinary(Assimp::StreamWriterLE& s); + void EndPropertiesBinary(Assimp::StreamWriterLE &s); + void EndPropertiesBinary(Assimp::StreamWriterLE &s, size_t num_properties); + void DumpChildrenBinary(Assimp::StreamWriterLE& s); + void EndBinary(Assimp::StreamWriterLE &s, bool has_children); + + void BeginAscii(std::ostream &s, int indent); + void DumpPropertiesAscii(std::ostream &s, int indent); + void BeginChildrenAscii(std::ostream &s, int indent); + void DumpChildrenAscii(std::ostream &s, int indent); + void EndAscii(std::ostream &s, int indent, bool has_children); private: // data used for binary dumps size_t start_pos; // starting position in stream @@ -169,11 +198,12 @@ public: // static member functions static void WritePropertyNode( const std::string& name, const T value, - Assimp::StreamWriterLE& s + Assimp::StreamWriterLE& s, + bool binary, int indent ) { FBX::Property p(value); FBX::Node node(name, p); - node.Dump(s); + node.Dump(s, binary, indent); } // convenience function to create and write a property node, @@ -182,7 +212,8 @@ public: // static member functions static void WritePropertyNode( const std::string& name, const std::vector& v, - Assimp::StreamWriterLE& s + Assimp::StreamWriterLE& s, + bool binary, int indent ); // convenience function to create and write a property node, @@ -191,8 +222,34 @@ public: // static member functions static void WritePropertyNode( const std::string& name, const std::vector& v, + Assimp::StreamWriterLE& s, + bool binary, int indent + ); + +private: // static helper functions + static void WritePropertyNodeAscii( + const std::string& name, + const std::vector& v, + Assimp::StreamWriterLE& s, + int indent + ); + static void WritePropertyNodeAscii( + const std::string& name, + const std::vector& v, + Assimp::StreamWriterLE& s, + int indent + ); + static void WritePropertyNodeBinary( + const std::string& name, + const std::vector& v, Assimp::StreamWriterLE& s ); + static void WritePropertyNodeBinary( + const std::string& name, + const std::vector& v, + Assimp::StreamWriterLE& s + ); + }; diff --git a/code/FBXExportProperty.cpp b/code/FBXExportProperty.cpp index e139bb95a..431750274 100644 --- a/code/FBXExportProperty.cpp +++ b/code/FBXExportProperty.cpp @@ -48,7 +48,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -#include // stringstream +#include +#include +#include // ostringstream // constructors for single element properties @@ -164,18 +166,18 @@ size_t FBX::Property::size() } } -void FBX::Property::Dump(Assimp::StreamWriterLE &s) +void FBX::Property::DumpBinary(Assimp::StreamWriterLE &s) { s.PutU1(type); - uint8_t* d; + uint8_t* d = data.data(); size_t N; switch (type) { - case 'C': s.PutU1(*(reinterpret_cast(data.data()))); return; - case 'Y': s.PutI2(*(reinterpret_cast(data.data()))); return; - case 'I': s.PutI4(*(reinterpret_cast(data.data()))); return; - case 'F': s.PutF4(*(reinterpret_cast(data.data()))); return; - case 'D': s.PutF8(*(reinterpret_cast(data.data()))); return; - case 'L': s.PutI8(*(reinterpret_cast(data.data()))); return; + case 'C': s.PutU1(*(reinterpret_cast(d))); return; + case 'Y': s.PutI2(*(reinterpret_cast(d))); return; + case 'I': s.PutI4(*(reinterpret_cast(d))); return; + case 'F': s.PutF4(*(reinterpret_cast(d))); return; + case 'D': s.PutF8(*(reinterpret_cast(d))); return; + case 'L': s.PutI8(*(reinterpret_cast(d))); return; case 'S': case 'R': s.PutU4(uint32_t(data.size())); @@ -187,7 +189,6 @@ void FBX::Property::Dump(Assimp::StreamWriterLE &s) s.PutU4(0); // no encoding (1 would be zip-compressed) // TODO: compress if large? s.PutU4(uint32_t(data.size())); // data size - d = data.data(); for (size_t i = 0; i < N; ++i) { s.PutI4((reinterpret_cast(d))[i]); } @@ -198,7 +199,6 @@ void FBX::Property::Dump(Assimp::StreamWriterLE &s) s.PutU4(0); // no encoding (1 would be zip-compressed) // TODO: compress if large? s.PutU4(uint32_t(data.size())); // data size - d = data.data(); for (size_t i = 0; i < N; ++i) { s.PutI8((reinterpret_cast(d))[i]); } @@ -209,7 +209,6 @@ void FBX::Property::Dump(Assimp::StreamWriterLE &s) s.PutU4(0); // no encoding (1 would be zip-compressed) // TODO: compress if large? s.PutU4(uint32_t(data.size())); // data size - d = data.data(); for (size_t i = 0; i < N; ++i) { s.PutF4((reinterpret_cast(d))[i]); } @@ -220,18 +219,146 @@ void FBX::Property::Dump(Assimp::StreamWriterLE &s) s.PutU4(0); // no encoding (1 would be zip-compressed) // TODO: compress if large? s.PutU4(uint32_t(data.size())); // data size - d = data.data(); for (size_t i = 0; i < N; ++i) { s.PutF8((reinterpret_cast(d))[i]); } return; default: - std::stringstream err; + std::ostringstream err; err << "Tried to dump property with invalid type '"; err << type << "'!"; throw DeadlyExportError(err.str()); } } +void FBX::Property::DumpAscii(Assimp::StreamWriterLE &outstream, int indent) +{ + std::ostringstream ss; + ss.imbue(std::locale::classic()); + ss.precision(15); // this seems to match official FBX SDK exports + DumpAscii(ss, indent); + outstream.PutString(ss.str()); +} + +void FBX::Property::DumpAscii(std::ostream& s, int indent) +{ + // no writing type... or anything. just shove it into the stream. + uint8_t* d = data.data(); + size_t N; + size_t swap = data.size(); + size_t count = 0; + switch (type) { + case 'C': + if (*(reinterpret_cast(d))) { s << 'T'; } + else { s << 'F'; } + return; + case 'Y': s << *(reinterpret_cast(d)); return; + case 'I': s << *(reinterpret_cast(d)); return; + case 'F': s << *(reinterpret_cast(d)); return; + case 'D': s << *(reinterpret_cast(d)); return; + case 'L': s << *(reinterpret_cast(d)); return; + case 'S': + // first search to see if it has "\x00\x01" in it - + // which separates fields which are reversed in the ascii version. + // yeah. + // FBX, yeah. + for (size_t i = 0; i < data.size(); ++i) { + if (data[i] == '\0') { + swap = i; + break; + } + } + case 'R': + s << '"'; + // we might as well check this now, + // probably it will never happen + for (size_t i = 0; i < data.size(); ++i) { + char c = data[i]; + if (c == '"') { + throw runtime_error("can't handle quotes in property string"); + } + } + // first write the SWAPPED member (if any) + for (size_t i = swap + 2; i < data.size(); ++i) { + char c = data[i]; + s << c; + } + // then a separator + if (swap != data.size()) { + s << "::"; + } + // then the initial member + for (size_t i = 0; i < swap; ++i) { + char c = data[i]; + s << c; + } + s << '"'; + return; + case 'i': + N = data.size() / 4; // number of elements + s << '*' << N << " {\n"; + for (int i = 0; i < indent + 1; ++i) { s << '\t'; } + s << "a: "; + for (size_t i = 0; i < N; ++i) { + if (i > 0) { s << ','; } + if (count++ > 120) { s << '\n'; count = 0; } + s << (reinterpret_cast(d))[i]; + } + s << '\n'; + for (int i = 0; i < indent; ++i) { s << '\t'; } + s << "} "; + return; + case 'l': + N = data.size() / 8; + s << '*' << N << " {\n"; + for (int i = 0; i < indent + 1; ++i) { s << '\t'; } + s << "a: "; + for (size_t i = 0; i < N; ++i) { + if (i > 0) { s << ','; } + if (count++ > 120) { s << '\n'; count = 0; } + s << (reinterpret_cast(d))[i]; + } + s << '\n'; + for (int i = 0; i < indent; ++i) { s << '\t'; } + s << "} "; + return; + case 'f': + N = data.size() / 4; + s << '*' << N << " {\n"; + for (int i = 0; i < indent + 1; ++i) { s << '\t'; } + s << "a: "; + for (size_t i = 0; i < N; ++i) { + if (i > 0) { s << ','; } + if (count++ > 120) { s << '\n'; count = 0; } + s << (reinterpret_cast(d))[i]; + } + s << '\n'; + for (int i = 0; i < indent; ++i) { s << '\t'; } + s << "} "; + return; + case 'd': + N = data.size() / 8; + s << '*' << N << " {\n"; + for (int i = 0; i < indent + 1; ++i) { s << '\t'; } + s << "a: "; + // set precision to something that can handle doubles + s.precision(15); + for (size_t i = 0; i < N; ++i) { + if (i > 0) { s << ','; } + if (count++ > 120) { s << '\n'; count = 0; } + s << (reinterpret_cast(d))[i]; + } + s << '\n'; + for (int i = 0; i < indent; ++i) { s << '\t'; } + s << "} "; + return; + default: + std::ostringstream err; + err << "Tried to dump property with invalid type '"; + err << type << "'!"; + throw runtime_error(err.str()); + } +} + #endif // ASSIMP_BUILD_NO_FBX_EXPORTER #endif // ASSIMP_BUILD_NO_EXPORT diff --git a/code/FBXExportProperty.h b/code/FBXExportProperty.h index 40a020688..cb3b0113f 100644 --- a/code/FBXExportProperty.h +++ b/code/FBXExportProperty.h @@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include #include // is_void namespace FBX { @@ -113,7 +114,10 @@ public: size_t size(); // write this property node as binary data to the given stream - void Dump(Assimp::StreamWriterLE &s); + void DumpBinary(Assimp::StreamWriterLE &s); + void DumpAscii(Assimp::StreamWriterLE &s, int indent=0); + void DumpAscii(std::ostream &s, int indent=0); + // note: make sure the ostream is in classic "C" locale private: char type; diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index 46782cc2e..e8846be08 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -66,7 +66,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include -#include // endl // RESOURCES: // https://code.blender.org/2013/08/fbx-binary-file-format-specification/ @@ -89,6 +88,8 @@ namespace FBX { "\xfa\xbc\xab\x09\xd0\xc8\xd4\x66\xb1\x76\xfb\x83\x1c\xf7\x26\x7e"; const std::string FOOT_MAGIC = "\xf8\x5a\x8c\x6a\xde\xf5\xd9\x7e\xec\xe9\x0c\xe3\x75\x8f\x29\x0b"; + const std::string COMMENT_UNDERLINE = + ";------------------------------------------------------------------"; } using namespace Assimp; @@ -115,7 +116,7 @@ namespace Assimp { // --------------------------------------------------------------------- // Worker function for exporting a scene to ASCII FBX. // Prototyped and registered in Exporter.cpp - /*void ExportSceneFBXA ( + void ExportSceneFBXA ( const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, @@ -126,7 +127,7 @@ namespace Assimp { // perform ascii export exporter.ExportAscii(pFile, pIOSystem); - }*/ // TODO + } } // end of namespace Assimp @@ -194,27 +195,43 @@ void FBXExporter::ExportAscii ( ); } - // this isn't really necessary, - // but the Autodesk FBX SDK puts a similar comment at the top of the file. - // Theirs declares that the file copyright is owned by Autodesk... - std::stringstream head; - using std::endl; - head << "; FBX " << EXPORT_VERSION_STR << " project file" << endl; - head << "; Created by the Open Asset Import Library (Assimp)" << endl; - head << "; http://assimp.org" << endl; - head << "; -------------------------------------------------" << endl; - head << endl; - const std::string ascii_header = head.str(); - outfile->Write(ascii_header.c_str(), ascii_header.size(), 1); + // write the ascii header + WriteAsciiHeader(); // write all the sections WriteAllNodes(); + // make sure the file ends with a newline. + // note: if the file is opened in text mode, + // this should do the right cross-platform thing. + outfile->Write("\n", 1, 1); + // explicitly release file pointer, // so we don't have to rely on class destruction. outfile.reset(); } +void FBXExporter::WriteAsciiHeader() +{ + // basically just a comment at the top of the file + std::stringstream head; + head << "; FBX " << EXPORT_VERSION_STR << " project file\n"; + head << "; Created by the Open Asset Import Library (Assimp)\n"; + head << "; http://assimp.org\n"; + head << "; -------------------------------------------------\n"; + const std::string ascii_header = head.str(); + outfile->Write(ascii_header.c_str(), ascii_header.size(), 1); +} + +void FBXExporter::WriteAsciiSectionHeader(const std::string& title) +{ + StreamWriterLE outstream(outfile); + std::stringstream s; + s << "\n\n; " << title << '\n'; + s << FBX::COMMENT_UNDERLINE << "\n"; + outstream.PutString(s.str()); +} + void FBXExporter::WriteBinaryHeader() { // first a specific sequence of 23 bytes, always the same @@ -294,28 +311,39 @@ void FBXExporter::WriteAllNodes () //FBXHeaderExtension top-level node void FBXExporter::WriteHeaderExtension () { + if (!binary) { + // no title, follows directly from the top comment + } FBX::Node n("FBXHeaderExtension"); StreamWriterLE outstream(outfile); + int indent = 0; // begin node - n.Begin(outstream); + n.Begin(outstream, binary, indent); // write properties // (none) // finish properties - n.EndProperties(outstream, 0); + n.EndProperties(outstream, binary, indent, 0); + + // begin children + n.BeginChildren(outstream, binary, indent); + + indent = 1; // write child nodes FBX::Node::WritePropertyNode( - "FBXHeaderVersion", int32_t(1003), outstream + "FBXHeaderVersion", int32_t(1003), outstream, binary, indent ); FBX::Node::WritePropertyNode( - "FBXVersion", int32_t(EXPORT_VERSION_INT), outstream - ); - FBX::Node::WritePropertyNode( - "EncryptionType", int32_t(0), outstream + "FBXVersion", int32_t(EXPORT_VERSION_INT), outstream, binary, indent ); + if (binary) { + FBX::Node::WritePropertyNode( + "EncryptionType", int32_t(0), outstream, binary, indent + ); + } FBX::Node CreationTimeStamp("CreationTimeStamp"); time_t rawtime; @@ -329,36 +357,50 @@ void FBXExporter::WriteHeaderExtension () CreationTimeStamp.AddChild("Minute", int32_t(now->tm_min)); CreationTimeStamp.AddChild("Second", int32_t(now->tm_sec)); CreationTimeStamp.AddChild("Millisecond", int32_t(0)); - CreationTimeStamp.Dump(outstream); + CreationTimeStamp.Dump(outstream, binary, indent); std::stringstream creator; creator << "Open Asset Import Library (Assimp) " << aiGetVersionMajor() << "." << aiGetVersionMinor() << "." << aiGetVersionRevision(); - FBX::Node::WritePropertyNode("Creator", creator.str(), outstream); + FBX::Node::WritePropertyNode( + "Creator", creator.str(), outstream, binary, indent + ); - FBX::Node sceneinfo("SceneInfo"); + //FBX::Node sceneinfo("SceneInfo"); //sceneinfo.AddProperty("GlobalInfo" + FBX::SEPARATOR + "SceneInfo"); // not sure if any of this is actually needed, // so just write an empty node for now. - sceneinfo.Dump(outstream); + //sceneinfo.Dump(outstream, binary, indent); + + indent = 0; // finish node - n.End(outstream, true); + n.End(outstream, binary, indent, true); // that's it for FBXHeaderExtension... + if (!binary) { return; } // but binary files also need top-level FileID, CreationTime, Creator: std::vector raw(GENERIC_FILEID.size()); for (size_t i = 0; i < GENERIC_FILEID.size(); ++i) { raw[i] = uint8_t(GENERIC_FILEID[i]); } - FBX::Node::WritePropertyNode("FileId", raw, outstream); - FBX::Node::WritePropertyNode("CreationTime", GENERIC_CTIME, outstream); - FBX::Node::WritePropertyNode("Creator", creator.str(), outstream); + FBX::Node::WritePropertyNode( + "FileId", raw, outstream, binary, indent + ); + FBX::Node::WritePropertyNode( + "CreationTime", GENERIC_CTIME, outstream, binary, indent + ); + FBX::Node::WritePropertyNode( + "Creator", creator.str(), outstream, binary, indent + ); } void FBXExporter::WriteGlobalSettings () { + if (!binary) { + // no title, follows directly from the header extension + } FBX::Node gs("GlobalSettings"); gs.AddChild("Version", int32_t(1000)); @@ -385,11 +427,15 @@ void FBXExporter::WriteGlobalSettings () p.AddP70int("CurrentTimeMarker", -1); gs.AddChild(p); - gs.Dump(outfile); + gs.Dump(outfile, binary, 0); } void FBXExporter::WriteDocuments () { + if (!binary) { + WriteAsciiSectionHeader("Documents Description"); + } + // not sure what the use of multiple documents would be, // or whether any end-application supports it FBX::Node docs("Documents"); @@ -411,16 +457,19 @@ void FBXExporter::WriteDocuments () doc.AddChild("RootNode", int64_t(0)); docs.AddChild(doc); - docs.Dump(outfile); + docs.Dump(outfile, binary, 0); } void FBXExporter::WriteReferences () { + if (!binary) { + WriteAsciiSectionHeader("Document References"); + } // always empty for now. // not really sure what this is for. FBX::Node n("References"); n.force_has_children = true; - n.Dump(outfile); + n.Dump(outfile, binary, 0); } @@ -469,9 +518,6 @@ size_t count_images(const aiScene* scene) { } } } - //for (auto &s : images) { - // std::cout << "found image: " << s << std::endl; - //} return images.size(); } @@ -511,6 +557,11 @@ void FBXExporter::WriteDefinitions () // determining how many of each type of object there are // and specifying the base properties to use when otherwise unspecified. + // ascii section header + if (!binary) { + WriteAsciiSectionHeader("Object definitions"); + } + // we need to count the objects int32_t count; int32_t total_count = 0; @@ -890,7 +941,7 @@ void FBXExporter::WriteDefinitions () defs.AddChild("Version", int32_t(100)); defs.AddChild("Count", int32_t(total_count)); for (auto &n : object_nodes) { defs.AddChild(n); } - defs.Dump(outfile); + defs.Dump(outfile, binary, 0); } @@ -936,14 +987,20 @@ int64_t to_ktime(double ticks, const aiAnimation* anim) { void FBXExporter::WriteObjects () { + if (!binary) { + WriteAsciiSectionHeader("Object properties"); + } // numbers should match those given in definitions! make sure to check StreamWriterLE outstream(outfile); FBX::Node object_node("Objects"); - object_node.Begin(outstream); - object_node.EndProperties(outstream); + int indent = 0; + object_node.Begin(outstream, binary, indent); + object_node.EndProperties(outstream, binary, indent); + object_node.BeginChildren(outstream, binary, indent); // geometry (aiMesh) mesh_uids.clear(); + indent = 1; for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) { // it's all about this mesh aiMesh* m = mScene->mMeshes[mi]; @@ -955,9 +1012,11 @@ void FBXExporter::WriteObjects () n.AddProperty(uid); n.AddProperty(FBX::SEPARATOR + "Geometry"); n.AddProperty("Mesh"); - n.Begin(outstream); - n.DumpProperties(outstream); - n.EndProperties(outstream); + n.Begin(outstream, binary, indent); + n.DumpProperties(outstream, binary, indent); + n.EndProperties(outstream, binary, indent); + n.BeginChildren(outstream, binary, indent); + indent = 2; // output vertex data - each vertex should be unique (probably) std::vector flattened_vertices; @@ -981,7 +1040,7 @@ void FBXExporter::WriteObjects () } } FBX::Node::WritePropertyNode( - "Vertices", flattened_vertices, outstream + "Vertices", flattened_vertices, outstream, binary, indent ); // output polygon data as a flattened array of vertex indices. @@ -997,30 +1056,38 @@ void FBXExporter::WriteObjects () ); } FBX::Node::WritePropertyNode( - "PolygonVertexIndex", polygon_data, outstream + "PolygonVertexIndex", polygon_data, outstream, binary, indent ); // here could be edges but they're insane. // it's optional anyway, so let's ignore it. FBX::Node::WritePropertyNode( - "GeometryVersion", int32_t(124), outstream + "GeometryVersion", int32_t(124), outstream, binary, indent ); // normals, if any if (m->HasNormals()) { FBX::Node normals("LayerElementNormal", int32_t(0)); - normals.Begin(outstream); - normals.DumpProperties(outstream); - normals.EndProperties(outstream); - FBX::Node::WritePropertyNode("Version", int32_t(101), outstream); - FBX::Node::WritePropertyNode("Name", "", outstream); + normals.Begin(outstream, binary, indent); + normals.DumpProperties(outstream, binary, indent); + normals.EndProperties(outstream, binary, indent); + normals.BeginChildren(outstream, binary, indent); + indent = 3; FBX::Node::WritePropertyNode( - "MappingInformationType", "ByPolygonVertex", outstream + "Version", int32_t(101), outstream, binary, indent + ); + FBX::Node::WritePropertyNode( + "Name", "", outstream, binary, indent + ); + FBX::Node::WritePropertyNode( + "MappingInformationType", "ByPolygonVertex", + outstream, binary, indent ); // TODO: vertex-normals or indexed normals when appropriate FBX::Node::WritePropertyNode( - "ReferenceInformationType", "Direct", outstream + "ReferenceInformationType", "Direct", + outstream, binary, indent ); std::vector normal_data; normal_data.reserve(3 * polygon_data.size()); @@ -1033,10 +1100,13 @@ void FBXExporter::WriteObjects () normal_data.push_back(n.z); } } - FBX::Node::WritePropertyNode("Normals", normal_data, outstream); + FBX::Node::WritePropertyNode( + "Normals", normal_data, outstream, binary, indent + ); // note: version 102 has a NormalsW also... not sure what it is, // so we can stick with version 101 for now. - normals.End(outstream, true); + indent = 2; + normals.End(outstream, binary, indent, true); } // uvs, if any @@ -1057,18 +1127,26 @@ void FBXExporter::WriteObjects () DefaultLogger::get()->warn(err.str()); } FBX::Node uv("LayerElementUV", int32_t(uvi)); - uv.Begin(outstream); - uv.DumpProperties(outstream); - uv.EndProperties(outstream); - FBX::Node::WritePropertyNode("Version", int32_t(101), outstream); + uv.Begin(outstream, binary, indent); + uv.DumpProperties(outstream, binary, indent); + uv.EndProperties(outstream, binary, indent); + uv.BeginChildren(outstream, binary, indent); + indent = 3; + FBX::Node::WritePropertyNode( + "Version", int32_t(101), outstream, binary, indent + ); // it doesn't seem like assimp keeps the uv map name, // so just leave it blank. - FBX::Node::WritePropertyNode("Name", "", outstream); FBX::Node::WritePropertyNode( - "MappingInformationType", "ByPolygonVertex", outstream + "Name", "", outstream, binary, indent ); FBX::Node::WritePropertyNode( - "ReferenceInformationType", "IndexToDirect", outstream + "MappingInformationType", "ByPolygonVertex", + outstream, binary, indent + ); + FBX::Node::WritePropertyNode( + "ReferenceInformationType", "IndexToDirect", + outstream, binary, indent ); std::vector uv_data; @@ -1093,9 +1171,14 @@ void FBXExporter::WriteObjects () } } } - FBX::Node::WritePropertyNode("UV", uv_data, outstream); - FBX::Node::WritePropertyNode("UVIndex", uv_indices, outstream); - uv.End(outstream, true); + FBX::Node::WritePropertyNode( + "UV", uv_data, outstream, binary, indent + ); + FBX::Node::WritePropertyNode( + "UVIndex", uv_indices, outstream, binary, indent + ); + indent = 2; + uv.End(outstream, binary, indent, true); } // i'm not really sure why this material section exists, @@ -1108,7 +1191,7 @@ void FBXExporter::WriteObjects () mat.AddChild("ReferenceInformationType", "IndexToDirect"); std::vector mat_indices = {0}; mat.AddChild("Materials", mat_indices); - mat.Dump(outstream); + mat.Dump(outstream, binary, indent); // finally we have the layer specifications, // which select the normals / UV set / etc to use. @@ -1127,10 +1210,11 @@ void FBXExporter::WriteObjects () le.AddChild("Type", "LayerElementUV"); le.AddChild("TypedIndex", int32_t(0)); layer.AddChild(le); - layer.Dump(outstream); + layer.Dump(outstream, binary, indent); // finish the node record - n.End(outstream, true); + indent = 1; + n.End(outstream, binary, indent, true); } // aiMaterial @@ -1274,7 +1358,7 @@ void FBXExporter::WriteObjects () n.AddChild(p); - n.Dump(outstream); + n.Dump(outstream, binary, indent); } // we need to look up all the images we're using, @@ -1322,7 +1406,7 @@ void FBXExporter::WriteObjects () n.AddChild("UseMipMap", int32_t(0)); n.AddChild("Filename", path); n.AddChild("RelativeFilename", path); - n.Dump(outstream); + n.Dump(outstream, binary, indent); } // Textures @@ -1441,7 +1525,7 @@ void FBXExporter::WriteObjects () tnode.AddChild( "Cropping", int32_t(0), int32_t(0), int32_t(0), int32_t(0) ); - tnode.Dump(outstream); + tnode.Dump(outstream, binary, indent); } } @@ -1594,7 +1678,7 @@ void FBXExporter::WriteObjects () // "acuracy"... this is not a typo.... dnode.AddChild("Link_DeformAcuracy", double(50)); dnode.AddChild("SkinningType", "Linear"); // TODO: other modes? - dnode.Dump(outstream); + dnode.Dump(outstream, binary, indent); // connect it connections.emplace_back("C", "OO", deformer_uid, mesh_uids[mi]); @@ -1738,7 +1822,7 @@ void FBXExporter::WriteObjects () // there's not really any way around this at the moment. // done - sdnode.Dump(outstream); + sdnode.Dump(outstream, binary, indent); // lastly, connect to the parent deformer connections.emplace_back( @@ -1856,7 +1940,7 @@ void FBXExporter::WriteObjects () } // now write it - bpnode.Dump(outstream); + bpnode.Dump(outstream, binary, indent); }*/ // TODO: cameras, lights @@ -1916,7 +2000,7 @@ void FBXExporter::WriteObjects () // this node absurdly always pretends it has children // (in this case it does, but just in case...) asnode.force_has_children = true; - asnode.Dump(outstream); + asnode.Dump(outstream, binary, indent); // note: animation stacks are not connected to anything } @@ -1931,7 +2015,7 @@ void FBXExporter::WriteObjects () // this node absurdly always pretends it has children alnode.force_has_children = true; - alnode.Dump(outstream); + alnode.Dump(outstream, binary, indent); // connect to the relevant animstack connections.emplace_back( @@ -2048,7 +2132,8 @@ void FBXExporter::WriteObjects () } } - object_node.End(outstream, true); + indent = 0; + object_node.End(outstream, binary, indent, true); } // convenience map of magic node name strings to FBX properties, @@ -2074,13 +2159,14 @@ const std::map> transform_types = { }; // write a single model node to the stream -void WriteModelNode( +void FBXExporter::WriteModelNode( StreamWriterLE& outstream, + bool binary, const aiNode* node, int64_t node_uid, const std::string& type, const std::vector>& transform_chain, - TransformInheritance inherit_type=TransformInheritance_RSrs + TransformInheritance inherit_type ){ const aiVector3D zero = {0, 0, 0}; const aiVector3D one = {1, 1, 1}; @@ -2148,7 +2234,7 @@ void WriteModelNode( m.AddChild("Shading", Property(true)); m.AddChild("Culling", Property("CullingOff")); - m.Dump(outstream); + m.Dump(outstream, binary, 1); } // wrapper for WriteModelNodes to create and pass a blank transform chain @@ -2249,9 +2335,13 @@ void FBXExporter::WriteModelNodes( node_uid ); // write model node - WriteModelNode(outstream, node, node_uid, "Mesh", transform_chain); + WriteModelNode( + outstream, binary, node, node_uid, "Mesh", transform_chain + ); } else if (limbnodes.count(node)) { - WriteModelNode(outstream, node, node_uid, "LimbNode", transform_chain); + WriteModelNode( + outstream, binary, node, node_uid, "LimbNode", transform_chain + ); // we also need to write a nodeattribute to mark it as a skeleton int64_t node_attribute_uid = generate_uid(); FBX::Node na("NodeAttribute"); @@ -2259,12 +2349,14 @@ void FBXExporter::WriteModelNodes( node_attribute_uid, FBX::SEPARATOR + "NodeAttribute", "LimbNode" ); na.AddChild("TypeFlags", Property("Skeleton")); - na.Dump(outstream); + na.Dump(outstream, binary, 1); // and connect them connections.emplace_back("C", "OO", node_attribute_uid, node_uid); } else { // generate a null node so we can add children to it - WriteModelNode(outstream, node, node_uid, "Null", transform_chain); + WriteModelNode( + outstream, binary, node, node_uid, "Null", transform_chain + ); } // if more than one child mesh, make nodes for each mesh @@ -2296,7 +2388,7 @@ void FBXExporter::WriteModelNodes( FBX::Node p("Properties70"); p.AddP70enum("InheritType", 1); m.AddChild(p); - m.Dump(outstream); + m.Dump(outstream, binary, 1); } } @@ -2325,7 +2417,7 @@ void FBXExporter::WriteAnimationCurveNode( p.AddP70numberA("d|Y", default_value.y); p.AddP70numberA("d|Z", default_value.z); n.AddChild(p); - n.Dump(outstream); + n.Dump(outstream, binary, 1); // connect to layer this->connections.emplace_back("C", "OO", uid, layer_uid); // connect to bone @@ -2356,7 +2448,7 @@ void FBXExporter::WriteAnimationCurve( "KeyAttrRefCount", std::vector{static_cast(times.size())} ); - n.Dump(outstream); + n.Dump(outstream, binary, 1); this->connections.emplace_back( "C", "OP", curve_uid, curvenode_uid, property_link ); @@ -2367,13 +2459,18 @@ void FBXExporter::WriteConnections () { // we should have completed the connection graph already, // so basically just dump it here + if (!binary) { + WriteAsciiSectionHeader("Object connections"); + } + // TODO: comments with names in the ascii version FBX::Node conn("Connections"); StreamWriterLE outstream(outfile); - conn.Begin(outstream); + conn.Begin(outstream, binary, 0); + conn.BeginChildren(outstream, binary, 0); for (auto &n : connections) { - n.Dump(outstream); + n.Dump(outstream, binary, 1); } - conn.End(outstream, !connections.empty()); + conn.End(outstream, binary, 0, !connections.empty()); connections.clear(); } diff --git a/code/FBXExporter.h b/code/FBXExporter.h index 553cf60fe..3b9de8acb 100644 --- a/code/FBXExporter.h +++ b/code/FBXExporter.h @@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_FBX_EXPORTER #include "FBXExportNode.h" // FBX::Node +#include "FBXCommon.h" // FBX::TransformInheritance #include //#include @@ -104,6 +105,9 @@ namespace Assimp void WriteBinaryHeader(); void WriteBinaryFooter(); + // ascii files have a comment at the top + void WriteAsciiHeader(); + // WriteAllNodes does the actual export. // It just calls all the Write
methods below in order. void WriteAllNodes(); @@ -126,6 +130,7 @@ namespace Assimp // WriteTakes(); // deprecated since at least 2015 (fbx 7.4) // helpers + void WriteAsciiSectionHeader(const std::string& title); void WriteModelNodes( Assimp::StreamWriterLE& s, const aiNode* node, @@ -139,6 +144,15 @@ namespace Assimp const std::unordered_set& limbnodes, std::vector>& transform_chain ); + void WriteModelNode( // nor this + StreamWriterLE& s, + bool binary, + const aiNode* node, + int64_t node_uid, + const std::string& type, + const std::vector>& xfm_chain, + FBX::TransformInheritance ti_type=FBX::TransformInheritance_RSrs + ); void WriteAnimationCurveNode( StreamWriterLE& outstream, int64_t uid, From 0dad1d0c04fdf4ee04bbb81c56a6cc1a5e45873f Mon Sep 17 00:00:00 2001 From: Tommy Date: Thu, 29 Mar 2018 01:46:59 +0200 Subject: [PATCH 118/278] FBX Export: fix Texture_Alpha_soutce typo. --- code/FBXExporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index e8846be08..4db9fc4d9 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -1521,7 +1521,7 @@ void FBXExporter::WriteObjects () tnode.AddChild("RelativeFilename", texture_path); tnode.AddChild("ModelUVTranslation", double(0.0), double(0.0)); tnode.AddChild("ModelUVScaling", double(1.0), double(1.0)); - tnode.AddChild("Texture_Alpha_Soutce", "None"); + tnode.AddChild("Texture_Alpha_Source", "None"); tnode.AddChild( "Cropping", int32_t(0), int32_t(0), int32_t(0), int32_t(0) ); From 4b2120ab5642b8341e350e1d68de86c328b500b0 Mon Sep 17 00:00:00 2001 From: Tommy Date: Thu, 29 Mar 2018 10:45:23 +0200 Subject: [PATCH 119/278] FBX Export: fix for geometric transform nodes with multiple children. --- code/FBXExporter.cpp | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index 4db9fc4d9..f31a98604 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -2258,15 +2258,6 @@ void FBXExporter::WriteModelNodes( // first collapse any expanded transformation chains created by FBX import. std::string node_name(node->mName.C_Str()); if (node_name.find(MAGIC_NODE_TAG) != std::string::npos) { - if (node->mNumChildren != 1) { - // this should never happen - std::stringstream err; - err << "FBX transformation node should have exactly 1 child,"; - err << " but " << node->mNumChildren << " found"; - err << " on node \"" << node_name << "\"!"; - throw DeadlyExportError(err.str()); - } - aiNode* next_node = node->mChildren[0]; auto pos = node_name.find(MAGIC_NODE_TAG) + MAGIC_NODE_TAG.size() + 1; std::string type_name = node_name.substr(pos); auto elem = transform_types.find(type_name); @@ -2300,10 +2291,16 @@ void FBXExporter::WriteModelNodes( err << elem->second.second; throw DeadlyExportError(err.str()); } - // now just continue to the next node - WriteModelNodes( - outstream, next_node, parent_uid, limbnodes, transform_chain - ); + // now continue on to any child nodes + for (unsigned i = 0; i < node->mNumChildren; ++i) { + WriteModelNodes( + outstream, + node->mChildren[i], + parent_uid, + limbnodes, + transform_chain + ); + } return; } From 4a4b9cd31bea4a64a85592cb8b8fa5d07863a50d Mon Sep 17 00:00:00 2001 From: Tommy Date: Thu, 29 Mar 2018 12:38:56 +0200 Subject: [PATCH 120/278] assimp_cmd: prettier and better-compressed node hierarchy. Also removed line and nesting limits. It's better to show all the info than to silently discard some. With the new compressed display, it is far less obtrusive anyway. --- tools/assimp_cmd/Info.cpp | 107 +++++++++++++++++++++++++++----------- 1 file changed, 78 insertions(+), 29 deletions(-) diff --git a/tools/assimp_cmd/Info.cpp b/tools/assimp_cmd/Info.cpp index c4d5fe189..ae858bfe8 100644 --- a/tools/assimp_cmd/Info.cpp +++ b/tools/assimp_cmd/Info.cpp @@ -46,12 +46,31 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Main.h" +#include +#include +#include + const char* AICMD_MSG_INFO_HELP_E = "assimp info [-r] [-v]\n" "\tPrint basic structure of a 3D model\n" "\t-r,--raw: No postprocessing, do a raw import\n" "\t-v,--verbose: Print verbose info such as node transform data\n"; +const std::string TREE_BRANCH_ASCII = "|-"; +const std::string TREE_BRANCH_UTF8 = "\xe2\x94\x9c\xe2\x95\xb4"; +const std::string TREE_STOP_ASCII = "'-"; +const std::string TREE_STOP_UTF8 = "\xe2\x94\x94\xe2\x95\xb4"; +const std::string TREE_CONTINUE_ASCII = "| "; +const std::string TREE_CONTINUE_UTF8 = "\xe2\x94\x82 "; + +// note: by default this is outputing utf-8 text. +// this is well supported on pretty much any linux terminal. +// if this causes problems on some platform, +// put an #ifdef to use the ascii version for that platform. +const std::string TREE_BRANCH = TREE_BRANCH_UTF8; +const std::string TREE_STOP = TREE_STOP_UTF8; +const std::string TREE_CONTINUE = TREE_CONTINUE_UTF8; + // ----------------------------------------------------------------------------------- unsigned int CountNodes(const aiNode* root) @@ -184,46 +203,77 @@ std::string FindPTypes(const aiScene* scene) } // ----------------------------------------------------------------------------------- -void PrintHierarchy(const aiNode* root, unsigned int maxnest, unsigned int maxline, - unsigned int cline, bool verbose, unsigned int cnest=0) -{ - if (cline++ >= maxline || cnest >= maxnest) { - return; +// Prettily print the node graph to stdout +void PrintHierarchy( + const aiNode* node, + const std::string &indent, + bool verbose, + bool last = false, + bool first = true +){ + // tree visualization + std::string branchchar; + if (first) { branchchar = ""; } + else if (last) { branchchar = TREE_STOP; } // "'-" + else { branchchar = TREE_BRANCH; } // "|-" + + // print the indent and the branch character and the name + std::cout << indent << branchchar << node->mName.C_Str(); + + // if there are meshes attached, indicate this + if (node->mNumMeshes) { + std::cout << " (mesh "; + bool sep = false; + for (size_t i=0; i < node->mNumMeshes; ++i) { + unsigned int mesh_index = node->mMeshes[i]; + if (sep) { std::cout << ", "; } + std::cout << mesh_index; + sep = true; + } + std::cout << ")"; } - for(unsigned int i = 0; i < cnest; ++i) { - printf("-- "); - } - printf("\'%s\', meshes: %u\n",root->mName.data,root->mNumMeshes); + // finish the line + std::cout << std::endl; + // in verbose mode, print the transform data as well if (verbose) { - // print the actual transform - //printf(","); + // indent to use + std::string indentadd; + if (last) { indentadd += " "; } + else { indentadd += TREE_CONTINUE; } // "| ".. + if (node->mNumChildren == 0) { indentadd += " "; } + else { indentadd += TREE_CONTINUE; } // .."| " aiVector3D s, r, t; - root->mTransformation.Decompose(s, r, t); + node->mTransformation.Decompose(s, r, t); if (s.x != 1.0 || s.y != 1.0 || s.z != 1.0) { - for(unsigned int i = 0; i < cnest; ++i) { printf(" "); } - printf(" S:[%f %f %f]\n", s.x, s.y, s.z); + std::cout << indent << indentadd; + printf(" S:[%f %f %f]\n", s.x, s.y, s.z); } if (r.x || r.y || r.z) { - for(unsigned int i = 0; i < cnest; ++i) { printf(" "); } - printf(" R:[%f %f %f]\n", r.x, r.y, r.z); + std::cout << indent << indentadd; + printf(" R:[%f %f %f]\n", r.x, r.y, r.z); } if (t.x || t.y || t.z) { - for(unsigned int i = 0; i < cnest; ++i) { printf(" "); } - printf(" T:[%f %f %f]\n", t.x, t.y, t.z); + std::cout << indent << indentadd; + printf(" T:[%f %f %f]\n", t.x, t.y, t.z); } } - //printf("\n"); - for (unsigned int i = 0; i < root->mNumChildren; ++i ) { - PrintHierarchy(root->mChildren[i],maxnest,maxline,cline,verbose,cnest+1); - if(i == root->mNumChildren-1) { - for(unsigned int i = 0; i < cnest; ++i) { - printf(" "); - } - printf("<--\n"); - } + // and recurse + std::string nextIndent; + if (first) { nextIndent = indent; } + else if (last) { nextIndent = indent + " "; } + else { nextIndent = indent + TREE_CONTINUE; } // "| " + for (size_t i = 0; i < node->mNumChildren; ++i) { + bool lastone = (i == node->mNumChildren - 1); + PrintHierarchy( + node->mChildren[i], + nextIndent, + verbose, + lastone, + false + ); } } @@ -406,8 +456,7 @@ int Assimp_Info (const char* const* params, unsigned int num) // node hierarchy printf("\nNode hierarchy:\n"); - unsigned int cline=0; - PrintHierarchy(scene->mRootNode,20,1000,cline,verbose); + PrintHierarchy(scene->mRootNode,"",verbose); printf("\n"); return 0; From 39d98784294ed7bfc5473cd5000b4d7cd7760ed4 Mon Sep 17 00:00:00 2001 From: Tommy Date: Thu, 29 Mar 2018 13:10:41 +0200 Subject: [PATCH 121/278] FBX Export: use ai_snprintf. --- code/FBXExportNode.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/FBXExportNode.cpp b/code/FBXExportNode.cpp index 514d5f360..a1171eca8 100644 --- a/code/FBXExportNode.cpp +++ b/code/FBXExportNode.cpp @@ -47,12 +47,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include // StreamWriterLE #include // DeadlyExportError #include +#include // ai_snprintf #include #include #include // ostringstream #include // shared_ptr -#include // snprintf // AddP70 helpers... there's no usable pattern here, // so all are defined as separate functions. @@ -442,7 +442,7 @@ void FBX::Node::WritePropertyNodeAscii( int count = 0; for (size_t i = 0; i < v.size(); ++i) { if (i > 0) { s.PutChar(','); } - int len = snprintf(buffer, sizeof(buffer), "%f", v[i]); + int len = ai_snprintf(buffer, sizeof(buffer), "%f", v[i]); count += len; if (count > 2048) { s.PutChar('\n'); count = 0; } if (len < 0 || len > 31) { @@ -478,7 +478,7 @@ void FBX::Node::WritePropertyNodeAscii( int count = 0; for (size_t i = 0; i < v.size(); ++i) { if (i > 0) { s.PutChar(','); } - int len = snprintf(buffer, sizeof(buffer), "%d", v[i]); + int len = ai_snprintf(buffer, sizeof(buffer), "%d", v[i]); count += len; if (count > 2048) { s.PutChar('\n'); count = 0; } if (len < 0 || len > 31) { From 070acfbaddc99db506b90667dc3026644561dcd8 Mon Sep 17 00:00:00 2001 From: Tommy Date: Thu, 29 Mar 2018 14:29:02 +0200 Subject: [PATCH 122/278] FBX Export: relax bindpose matrix check slightly. Apparently +/- 1e-5 is too strict. --- code/FBXExporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index f31a98604..c524e3911 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -1784,7 +1784,7 @@ void FBXExporter::WriteObjects () // this should be the same as the bone's mOffsetMatrix. // if it's not the same, the skeleton isn't in the bind pose. - const float epsilon = 1e-5f; // some error is to be expected + const float epsilon = 1e-4f; // some error is to be expected bool bone_xform_okay = true; if (b && ! tr.Equal(b->mOffsetMatrix, epsilon)) { not_in_bind_pose.insert(b); From 26ac2ffb6c4cb321c3431db57d5ba0958c5f6fa0 Mon Sep 17 00:00:00 2001 From: Alexis Breust Date: Thu, 29 Mar 2018 15:52:05 +0200 Subject: [PATCH 123/278] Not duplicating textures for embedded ones --- code/glTF2Exporter.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index b873d9d22..e146327ea 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -316,11 +316,9 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref& texture, aiTe std::string path = tex.C_Str(); if (path.size() > 0) { - if (path[0] != '*') { - std::map::iterator it = mTexturesByPath.find(path); - if (it != mTexturesByPath.end()) { - texture = mAsset->textures.Get(it->second); - } + std::map::iterator it = mTexturesByPath.find(path); + if (it != mTexturesByPath.end()) { + texture = mAsset->textures.Get(it->second); } if (!texture) { From 4919d3da2f772bfe6bff487e8345fcb2215ddbdb Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 30 Mar 2018 16:58:11 +0200 Subject: [PATCH 124/278] closes https://github.com/assimp/assimp/issues/1836: make documentation much more clear how to apply global scaling. --- code/CMakeLists.txt | 4 ++-- code/FBXConverter.h | 2 ++ code/ScaleProcess.cpp | 7 ------- include/assimp/postprocess.h | 6 ++++-- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index dafe017ef..7ae1a7e63 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -177,8 +177,6 @@ SET( Common_SRCS SkeletonMeshBuilder.cpp SplitByBoneCountProcess.cpp SplitByBoneCountProcess.h - ScaleProcess.cpp - ScaleProcess.h StandardShapes.cpp TargetAnimation.cpp TargetAnimation.h @@ -586,6 +584,8 @@ SET( PostProcessing_SRCS PolyTools.h MakeVerboseFormat.cpp MakeVerboseFormat.h + ScaleProcess.cpp + ScaleProcess.h ) SOURCE_GROUP( PostProcessing FILES ${PostProcessing_SRCS}) diff --git a/code/FBXConverter.h b/code/FBXConverter.h index 06a6f07a7..26ba3cb4e 100644 --- a/code/FBXConverter.h +++ b/code/FBXConverter.h @@ -443,6 +443,8 @@ private: aiScene* const out; const FBX::Document& doc; + + std::vector mLightNames; }; } diff --git a/code/ScaleProcess.cpp b/code/ScaleProcess.cpp index 0f60fbdb4..facc39d7d 100644 --- a/code/ScaleProcess.cpp +++ b/code/ScaleProcess.cpp @@ -88,13 +88,6 @@ void ScaleProcess::Execute( aiScene* pScene ) { void ScaleProcess::traverseNodes( aiNode *node ) { applyScaling( node ); - - /*for ( unsigned int i = 0; i < node->mNumChildren; ++i ) { - aiNode *currentNode = currentNode->mChildren[ i ]; - if ( nullptr != currentNode ) { - traverseNodes( currentNode ); - } - }*/ } void ScaleProcess::applyScaling( aiNode *currentNode ) { diff --git a/include/assimp/postprocess.h b/include/assimp/postprocess.h index ebb6728f3..f6c0833ee 100644 --- a/include/assimp/postprocess.h +++ b/include/assimp/postprocess.h @@ -537,9 +537,11 @@ enum aiPostProcessSteps /**
This step will perform a global scale of the model. * * Some importers are providing a mechanism to define a scaling unit for the - * model. This post processing step can be used to do so. + * model. This post processing step can be used to do so. You need to get the + * global scaling from your importer settings like in FBX. Use the flag + * AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY from the global property table to configure this. * - * Use #AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY to control this. + * Use #AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY to setup the global scaing factor. */ aiProcess_GlobalScale = 0x8000000, From c97fb99435b80da87cae138fb026f764cc672cf7 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 31 Mar 2018 16:37:39 +0200 Subject: [PATCH 125/278] closes https://github.com/assimp/assimp/issues/1855: fix correction of node names. --- code/FBXConverter.cpp | 118 +++++++++++++++++++----------------------- code/FBXConverter.h | 29 ++++------- 2 files changed, 63 insertions(+), 84 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index f3a908dd4..cf5d42de2 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -61,6 +61,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include +#include namespace Assimp { namespace FBX { @@ -133,9 +135,7 @@ void Converter::ConvertRootNode() { ConvertNodes( 0L, *out->mRootNode ); } - -void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform ) -{ +void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform ) { const std::vector& conns = doc.GetConnectionsByDestinationSequenced( id, "Model" ); std::vector nodes; @@ -153,14 +153,14 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa } const Object* const object = con->SourceObject(); - if ( !object ) { + if ( nullptr == object ) { FBXImporter::LogWarn( "failed to convert source object for Model link" ); continue; } const Model* const model = dynamic_cast( object ); - if ( model ) { + if ( nullptr != model ) { nodes_chain.clear(); post_nodes_chain.clear(); @@ -174,7 +174,7 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa ai_assert( nodes_chain.size() ); - const std::string& original_name = FixNodeName( model->Name() ); + std::string original_name = FixNodeName( model->Name() ); // check if any of the nodes in the chain has the name the fbx node // is supposed to have. If there is none, add another node to @@ -189,7 +189,15 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa } if ( !name_carrier ) { + NodeNameCache::const_iterator it( std::find( mNodeNames.begin(), mNodeNames.end(), original_name ) ); + if ( it != mNodeNames.end() ) { + original_name = original_name + std::string( "001" ); + } + + mNodeNames.push_back( original_name ); nodes_chain.push_back( new aiNode( original_name ) ); + } else { + original_name = nodes_chain.back()->mName.C_Str(); } //setup metadata on newest node @@ -250,11 +258,11 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa ConvertNodes( model->ID(), *last_parent, new_abs_transform ); if ( doc.Settings().readLights ) { - ConvertLights( *model ); + ConvertLights( *model, original_name ); } if ( doc.Settings().readCameras ) { - ConvertCameras( *model ); + ConvertCameras( *model, original_name ); } nodes.push_back( nodes_chain.front() ); @@ -278,34 +286,31 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa } -void Converter::ConvertLights( const Model& model ) -{ +void Converter::ConvertLights( const Model& model, const std::string &orig_name ) { const std::vector& node_attrs = model.GetAttributes(); for( const NodeAttribute* attr : node_attrs ) { const Light* const light = dynamic_cast( attr ); if ( light ) { - ConvertLight( model, *light ); + ConvertLight( *light, orig_name ); } } } -void Converter::ConvertCameras( const Model& model ) -{ +void Converter::ConvertCameras( const Model& model, const std::string &orig_name ) { const std::vector& node_attrs = model.GetAttributes(); for( const NodeAttribute* attr : node_attrs ) { const Camera* const cam = dynamic_cast( attr ); if ( cam ) { - ConvertCamera( model, *cam ); + ConvertCamera( *cam, orig_name ); } } } -void Converter::ConvertLight( const Model& model, const Light& light ) -{ +void Converter::ConvertLight( const Light& light, const std::string &orig_name ) { lights.push_back( new aiLight() ); aiLight* const out_light = lights.back(); - out_light->mName.Set( FixNodeName( model.Name() ) ); + out_light->mName.Set( orig_name ); const float intensity = light.Intensity() / 100.0f; const aiVector3D& col = light.Color(); @@ -378,12 +383,12 @@ void Converter::ConvertLight( const Model& model, const Light& light ) } } -void Converter::ConvertCamera( const Model& model, const Camera& cam ) +void Converter::ConvertCamera( const Camera& cam, const std::string &orig_name ) { cameras.push_back( new aiCamera() ); aiCamera* const out_camera = cameras.back(); - out_camera->mName.Set( FixNodeName( model.Name() ) ); + out_camera->mName.Set( orig_name ); out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight(); @@ -397,6 +402,31 @@ void Converter::ConvertCamera( const Model& model, const Camera& cam ) out_camera->mClipPlaneFar = cam.FarPlane(); } +static bool HasName( NodeNameCache &cache, const std::string &name ) { + NodeNameCache::const_iterator it( std::find( cache.begin(), cache.end(), name ) ); + return it != cache.end(); + +} +void Converter::GetUniqueName( const std::string &name, std::string uniqueName ) { + if ( !HasName( mNodeNames, name ) ) { + uniqueName = name; + return; + } + + int i( 0 ); + std::string newName; + while ( HasName( mNodeNames, newName ) ) { + ++i; + newName.clear(); + newName += name; + std::stringstream ext; + ext << std::setfill( '0' ) << std::setw( 3 ) << i; + newName += ext.str(); + } + uniqueName = newName; + mNodeNames.push_back( uniqueName ); +} + const char* Converter::NameTransformationComp( TransformationComp comp ) { @@ -738,7 +768,7 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector // not be guaranteed. ai_assert( NeedsComplexTransformationChain( model ) == is_complex ); - const std::string& name = FixNodeName( model.Name() ); + std::string name = FixNodeName( model.Name() ); // now, if we have more than just Translation, Scaling and Rotation, // we need to generate a full node chain to accommodate for assimp's @@ -786,8 +816,10 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector // else, we can just multiply the matrices together aiNode* nd = new aiNode(); output_nodes.push_back( nd ); + std::string uniqueName; + GetUniqueName( name, uniqueName ); - nd->mName.Set( name ); + nd->mName.Set( uniqueName ); for (const auto &transform : chain) { nd->mTransformation = nd->mTransformation * transform; @@ -2005,50 +2037,6 @@ void Converter::ConvertAnimations() } } -void Converter::RenameNode( const std::string& fixed_name, const std::string& new_name ) { - if ( node_names.find( fixed_name ) == node_names.end() ) { - FBXImporter::LogError( "Cannot rename node " + fixed_name + ", not existing."); - return; - } - - if ( node_names.find( new_name ) != node_names.end() ) { - FBXImporter::LogError( "Cannot rename node " + fixed_name + " to " + new_name +", name already existing." ); - return; - } - - ai_assert( node_names.find( fixed_name ) != node_names.end() ); - ai_assert( node_names.find( new_name ) == node_names.end() ); - - renamed_nodes[ fixed_name ] = new_name; - - const aiString fn( fixed_name ); - - for( aiCamera* cam : cameras ) { - if ( cam->mName == fn ) { - cam->mName.Set( new_name ); - break; - } - } - - for( aiLight* light : lights ) { - if ( light->mName == fn ) { - light->mName.Set( new_name ); - break; - } - } - - for( aiAnimation* anim : animations ) { - for ( unsigned int i = 0; i < anim->mNumChannels; ++i ) { - aiNodeAnim* const na = anim->mChannels[ i ]; - if ( na->mNodeName == fn ) { - na->mNodeName.Set( new_name ); - break; - } - } - } -} - - std::string Converter::FixNodeName( const std::string& name ) { // strip Model:: prefix, avoiding ambiguities (i.e. don't strip if diff --git a/code/FBXConverter.h b/code/FBXConverter.h index 26ba3cb4e..7ae68c5e5 100644 --- a/code/FBXConverter.h +++ b/code/FBXConverter.h @@ -68,6 +68,8 @@ namespace FBX { class Document; +using NodeNameCache = std::vector; + /** * Convert a FBX #Document to #aiScene * @param out Empty scene to be populated @@ -117,16 +119,19 @@ private: void ConvertNodes(uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform = aiMatrix4x4()); // ------------------------------------------------------------------------------------------------ - void ConvertLights(const Model& model); + void ConvertLights(const Model& model, const std::string &orig_name ); // ------------------------------------------------------------------------------------------------ - void ConvertCameras(const Model& model); + void ConvertCameras(const Model& model, const std::string &orig_name ); // ------------------------------------------------------------------------------------------------ - void ConvertLight(const Model& model, const Light& light); + void ConvertLight( const Light& light, const std::string &orig_name ); // ------------------------------------------------------------------------------------------------ - void ConvertCamera(const Model& model, const Camera& cam); + void ConvertCamera( const Camera& cam, const std::string &orig_name ); + + // ------------------------------------------------------------------------------------------------ + void GetUniqueName( const std::string &name, std::string uniqueName ); // ------------------------------------------------------------------------------------------------ // this returns unified names usable within assimp identifiers (i.e. no space characters - @@ -258,18 +263,6 @@ private: // convert animation data to aiAnimation et al void ConvertAnimations(); - // ------------------------------------------------------------------------------------------------ - // rename a node already partially converted. fixed_name is a string previously returned by - // FixNodeName, new_name specifies the string FixNodeName should return on all further invocations - // which would previously have returned the old value. - // - // this also updates names in node animations, cameras and light sources and is thus slow. - // - // NOTE: the caller is responsible for ensuring that the new name is unique and does - // not collide with any other identifiers. The best way to ensure this is to only - // append to the old name, which is guaranteed to match these requirements. - void RenameNode(const std::string& fixed_name, const std::string& new_name); - // ------------------------------------------------------------------------------------------------ // takes a fbx node name and returns the identifier to be used in the assimp output scene. // the function is guaranteed to provide consistent results over multiple invocations @@ -281,7 +274,6 @@ private: // XXX: better use multi_map .. typedef std::map > NodeMap; - // ------------------------------------------------------------------------------------------------ void ConvertAnimationStack(const AnimationStack& st); @@ -439,12 +431,11 @@ private: typedef std::map NameNameMap; NameNameMap renamed_nodes; + NodeNameCache mNodeNames; double anim_fps; aiScene* const out; const FBX::Document& doc; - - std::vector mLightNames; }; } From 2a5728b4c3149feee04a7becda1704e17cd01f50 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 31 Mar 2018 17:25:29 +0200 Subject: [PATCH 126/278] FBX-Importer: fix usage of deprecated include. --- code/FBXConverter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index cf5d42de2..89e0d3edc 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -61,7 +61,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include -#include +#include #include namespace Assimp { From f3cc2f79fccd490c6a2a47e0938d49fb87768fd0 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 31 Mar 2018 17:30:31 +0200 Subject: [PATCH 127/278] FBX-Importer: remove unused lookup table. --- code/FBXConverter.cpp | 6 ++---- code/FBXConverter.h | 3 --- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 89e0d3edc..9f275b7cb 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -2054,8 +2054,7 @@ std::string Converter::FixNodeName( const std::string& name ) } node_names[ temp ] = true; - const NameNameMap::const_iterator rit = renamed_nodes.find( temp ); - return rit == renamed_nodes.end() ? temp : ( *rit ).second; + return temp; } const NodeNameMap::const_iterator it = node_names.find( name ); @@ -2066,8 +2065,7 @@ std::string Converter::FixNodeName( const std::string& name ) } node_names[ name ] = false; - const NameNameMap::const_iterator rit = renamed_nodes.find( name ); - return rit == renamed_nodes.end() ? name : ( *rit ).second; + return name; } void Converter::ConvertAnimationStack( const AnimationStack& st ) diff --git a/code/FBXConverter.h b/code/FBXConverter.h index 7ae68c5e5..83e469e3c 100644 --- a/code/FBXConverter.h +++ b/code/FBXConverter.h @@ -428,9 +428,6 @@ private: typedef std::map NodeNameMap; NodeNameMap node_names; - typedef std::map NameNameMap; - NameNameMap renamed_nodes; - NodeNameCache mNodeNames; double anim_fps; From c9bb3592ff8c3866ac0dcc8f2b2089caba06879f Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 31 Mar 2018 18:10:29 +0200 Subject: [PATCH 128/278] FBX-Importer: remove unused lookup tables for nodes. --- code/FBXConverter.cpp | 20 +------------------- code/FBXConverter.h | 4 ---- 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 9f275b7cb..2c9818a16 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -2037,34 +2037,16 @@ void Converter::ConvertAnimations() } } -std::string Converter::FixNodeName( const std::string& name ) -{ +std::string Converter::FixNodeName( const std::string& name ) { // strip Model:: prefix, avoiding ambiguities (i.e. don't strip if // this causes ambiguities, well possible between empty identifiers, // such as "Model::" and ""). Make sure the behaviour is consistent // across multiple calls to FixNodeName(). if ( name.substr( 0, 7 ) == "Model::" ) { std::string temp = name.substr( 7 ); - - const NodeNameMap::const_iterator it = node_names.find( temp ); - if ( it != node_names.end() ) { - if ( !( *it ).second ) { - return FixNodeName( name + "_" ); - } - } - node_names[ temp ] = true; - return temp; } - const NodeNameMap::const_iterator it = node_names.find( name ); - if ( it != node_names.end() ) { - if ( ( *it ).second ) { - return FixNodeName( name + "_" ); - } - } - node_names[ name ] = false; - return name; } diff --git a/code/FBXConverter.h b/code/FBXConverter.h index 83e469e3c..60fd04e2c 100644 --- a/code/FBXConverter.h +++ b/code/FBXConverter.h @@ -424,10 +424,6 @@ private: typedef std::map NodeAnimBitMap; NodeAnimBitMap node_anim_chain_bits; - // name -> has had its prefix_stripped? - typedef std::map NodeNameMap; - NodeNameMap node_names; - NodeNameCache mNodeNames; double anim_fps; From dbf32abfb2c3e2d4eff327d4e7dd806ce6b2d043 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 31 Mar 2018 18:51:31 +0200 Subject: [PATCH 129/278] Build: use c++11 in openddl-parser as well. --- CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0026dcb7f..ffd978562 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -138,8 +138,7 @@ SET (PROJECT_VERSION "${ASSIMP_VERSION}") SET( ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources" ) -# Needed for openddl_parser config, no use of c++11 at this moment -ADD_DEFINITIONS( -DOPENDDL_NO_USE_CPP11 ) +# Enable C++1 globally set_property( GLOBAL PROPERTY CXX_STANDARD 11 ) # Get the current working branch From 417c4fcb457ab8282e8698596cba2de99c604e92 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 31 Mar 2018 18:53:00 +0200 Subject: [PATCH 130/278] Cmake: remove dead code. --- CMakeLists.txt | 8 -------- 1 file changed, 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ffd978562..f48fcd773 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -191,14 +191,6 @@ SET(CPACK_COMPONENTS_ALL assimp-bin ${LIBASSIMP_COMPONENT} ${LIBASSIMP-DEV_COMPO SET(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names") IF( UNIX ) - # Ensure that we do not run into issues like http://www.tcm.phy.cam.ac.uk/sw/inodes64.html on 32 bit linux - IF( ${OPERATING_SYSTEM} MATCHES "Android") - ELSE() - IF ( CMAKE_SIZEOF_VOID_P EQUAL 4) # only necessary for 32-bit linux - #ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 ) - ENDIF() - ENDIF() - # Use GNUInstallDirs for Unix predefined directories INCLUDE(GNUInstallDirs) ENDIF( UNIX ) From 676e1c956561273986a74029915cfdea8ede30a9 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 31 Mar 2018 19:12:53 +0200 Subject: [PATCH 131/278] Cmake: adapt cmake script for VS2017 --- CMakeLists.txt | 108 +++++++++++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 52 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f48fcd773..83e1be081 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -160,7 +160,7 @@ EXECUTE_PROCESS( ) IF(NOT GIT_COMMIT_HASH) - SET(GIT_COMMIT_HASH 0) + SET(GIT_COMMIT_HASH 0) ENDIF(NOT GIT_COMMIT_HASH) IF(ASSIMP_DOUBLE_PRECISION) @@ -178,10 +178,10 @@ CONFIGURE_FILE( ) INCLUDE_DIRECTORIES( - ./ - include - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_BINARY_DIR}/include + ./ + include + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/include ) LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules" ) @@ -203,13 +203,13 @@ IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW) SET(LIBSTDC++_LIBRARIES -lstdc++) ELSEIF(MSVC) # enable multi-core compilation with MSVC - add_compile_options(/MP) - if("${CMAKE_GENERATOR}" MATCHES "(Win64|IA64)") - add_compile_options( /bigobj ) - endif() + ADD_COMPILE_OPTIONS(/MP) + IF("${CMAKE_GENERATOR}" MATCHES "(Win64|IA64)") + ADD_COMPILE_OPTIONS( /bigobj ) + ENDIF() # disable "elements of array '' will be default initialized" warning on MSVC2013 IF(MSVC12) - add_compile_options(/wd4351) + ADD_COMPILE_OPTIONS(/wd4351) ENDIF() ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fvisibility=hidden -fPIC -Wall -Wno-long-long -std=c++11" ) @@ -220,39 +220,39 @@ ELSEIF( CMAKE_COMPILER_IS_MINGW ) ADD_DEFINITIONS( -U__STRICT_ANSI__ ) ENDIF() -if (IOS) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -O3") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3") -endif() +IF (IOS) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -O3") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3") +ENDIF() -if (ASSIMP_COVERALLS) - MESSAGE(STATUS "Coveralls enabled") - INCLUDE(Coveralls) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") -endif() +IF (ASSIMP_COVERALLS) + MESSAGE(STATUS "Coveralls enabled") + INCLUDE(Coveralls) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") +ENDIF() -if (ASSIMP_WERROR) +IF (ASSIMP_WERROR) MESSAGE(STATUS "Treating warnings as errors") IF (MSVC) - add_compile_options(/WX) + ADD_COMPILE_OPTIONS(/WX) ELSE() SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") ENDIF() -endif() +ENDIF() -if (ASSIMP_ASAN) - MESSAGE(STATUS "AddressSanitizer enabled") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") -endif() +IF (ASSIMP_ASAN) + MESSAGE(STATUS "AddressSanitizer enabled") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") +ENDIF() -if (ASSIMP_UBSAN) - MESSAGE(STATUS "Undefined Behavior sanitizer enabled") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") -endif() +IF (ASSIMP_UBSAN) + MESSAGE(STATUS "Undefined Behavior sanitizer enabled") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") +ENDIF() INCLUDE (FindPkgMacros) INCLUDE (PrecompiledHeader) @@ -285,42 +285,42 @@ ENDIF() IF (NOT TARGET uninstall) # add make uninstall capability CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) - add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") + ADD_CUSTOM_TARGET(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") ENDIF() # cmake configuration files CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" @ONLY IMMEDIATE) CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config-version.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" @ONLY IMMEDIATE) -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT}) +INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT}) FIND_PACKAGE( DirectX ) IF( BUILD_DOCS ) - add_subdirectory(doc) + ADD_SUBDIRECTORY(doc) ENDIF( BUILD_DOCS ) # Look for system installed irrXML IF ( SYSTEM_IRRXML ) - find_package( IrrXML REQUIRED ) + FIND_PACKAGE( IrrXML REQUIRED ) ENDIF( SYSTEM_IRRXML ) # Search for external dependencies, and build them from source if not found # Search for zlib IF ( NOT ASSIMP_BUILD_ZLIB ) - find_package(ZLIB) + FIND_PACKAGE(ZLIB) ENDIF( NOT ASSIMP_BUILD_ZLIB ) IF( NOT ZLIB_FOUND ) - message(STATUS "compiling zlib from souces") + MESSAGE(STATUS "compiling zlib from souces") INCLUDE(CheckIncludeFile) INCLUDE(CheckTypeSize) INCLUDE(CheckFunctionExists) # compile from sources - add_subdirectory(contrib/zlib) + ADD_SUBDIRECTORY(contrib/zlib) SET(ZLIB_FOUND 1) SET(ZLIB_LIBRARIES zlibstatic) SET(ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/contrib/zlib ${CMAKE_CURRENT_BINARY_DIR}/contrib/zlib) -else(NOT ZLIB_FOUND) +ELSE(NOT ZLIB_FOUND) ADD_DEFINITIONS(-DASSIMP_BUILD_NO_OWN_ZLIB) SET(ZLIB_LIBRARIES_LINKED -lz) ENDIF(NOT ZLIB_FOUND) @@ -362,7 +362,9 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/includes") # pick the correct prebuilt library - IF(MSVC14) + IF(MSVC15) + SET(C4D_LIB_POSTFIX "_2017") + ELSEIF(MSVC14) SET(C4D_LIB_POSTFIX "_2015") ELSEIF(MSVC12) SET(C4D_LIB_POSTFIX "_2013") @@ -403,7 +405,7 @@ ADD_SUBDIRECTORY(contrib) ADD_SUBDIRECTORY( code/ ) IF ( ASSIMP_BUILD_ASSIMP_TOOLS ) IF ( WIN32 AND DirectX_D3DX9_LIBRARY ) - option ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" ${DirectX_FOUND} ) + OPTION ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" ${DirectX_FOUND} ) IF ( ASSIMP_BUILD_ASSIMP_VIEW ) ADD_SUBDIRECTORY( tools/assimp_view/ ) ENDIF ( ASSIMP_BUILD_ASSIMP_VIEW ) @@ -467,8 +469,8 @@ IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES) SET(CPACK_PACKAGE_INSTALL_DIRECTORY "assimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}") SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") - string(TOUPPER ${LIBASSIMP_COMPONENT} "LIBASSIMP_COMPONENT_UPPER") - string(TOUPPER ${LIBASSIMP-DEV_COMPONENT} "LIBASSIMP-DEV_COMPONENT_UPPER") + STRING(TOUPPER ${LIBASSIMP_COMPONENT} "LIBASSIMP_COMPONENT_UPPER") + STRING(TOUPPER ${LIBASSIMP-DEV_COMPONENT} "LIBASSIMP-DEV_COMPONENT_UPPER") SET(CPACK_COMPONENT_ASSIMP-BIN_DISPLAY_NAME "tools") SET(CPACK_COMPONENT_ASSIMP-BIN_DEPENDS "${LIBASSIMP_COMPONENT}" ) @@ -498,8 +500,8 @@ IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES) SET(CPACK_DEBIAN_DISTRIBUTION_RELEASES lucid maverick natty oneiric precise CACHE STRING "Release code-names of the distrubiton release") ENDIF() SET(DPUT_HOST "" CACHE STRING "PPA repository to upload the debian sources") - include(CPack) - include(DebSourcePPA) + INCLUDE(CPack) + INCLUDE(DebSourcePPA) ENDIF() if(WIN32) @@ -511,14 +513,16 @@ if(WIN32) SET(LIB_DIR "${PROJECT_SOURCE_DIR}/lib32/") ENDIF() - if(MSVC12) + IF(MSVC12) SET(ASSIMP_MSVC_VERSION "vc120") - elseif(MSVC14) + ELSEIF(MSVC14) SET(ASSIMP_MSVC_VERSION "vc140") + ELSEIF(MSVC15) + SET(ASSIMP_MSVC_VERSION "vc141") ENDIF(MSVC12) - if(MSVC12 OR MSVC14) - add_custom_target(UpdateAssimpLibsDebugSymbolsAndDLLs COMMENT "Copying Assimp Libraries ..." VERBATIM) + IF(MSVC12 OR MSVC14 OR MSVC15 ) + ADD_CUSTOM_TARGET(UpdateAssimpLibsDebugSymbolsAndDLLs COMMENT "Copying Assimp Libraries ..." VERBATIM) IF(CMAKE_GENERATOR MATCHES "^Visual Studio") ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.dll VERBATIM) ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.exp VERBATIM) @@ -539,5 +543,5 @@ if(WIN32) ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM) ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM) ENDIF() - ENDIF(MSVC12 OR MSVC14) + ENDIF(MSVC12 OR MSVC14 OR MSVC15 ) ENDIF (WIN32) From 04c65ccdcbd6b3f7d55920351648715aedb3557f Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 1 Apr 2018 17:16:14 +0200 Subject: [PATCH 132/278] closes https://github.com/assimp/assimp/issues/1831: make config CMAKE_LIBRARY_CONFIG overridable. --- assimp-config.cmake.in | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/assimp-config.cmake.in b/assimp-config.cmake.in index e06cc10ee..5031c8f8d 100644 --- a/assimp-config.cmake.in +++ b/assimp-config.cmake.in @@ -34,36 +34,18 @@ if( MSVC ) else() set(MSVC_PREFIX "vc150") endif() - set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" FORCE) + set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" ) else() - set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@" CACHE STRING "the suffix for the openrave libraries" FORCE) + set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@" CACHE STRING "the suffix for the openrave libraries" ) endif() set( ASSIMP_CXX_FLAGS ) # dynamically linked library -if( WIN32 ) - # for visual studio linking, most of the time boost dlls will be used - set( ASSIMP_CXX_FLAGS " -DBOOST_ALL_DYN_LINK -DBOOST_ALL_NO_LIB") -endif() set( ASSIMP_LINK_FLAGS "" ) set( ASSIMP_LIBRARY_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_LIB_INSTALL_DIR@") set( ASSIMP_INCLUDE_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_INCLUDE_INSTALL_DIR@") set( ASSIMP_LIBRARIES assimp${ASSIMP_LIBRARY_SUFFIX}) set( ASSIMP_LIBRARIES ${ASSIMP_LIBRARIES}@CMAKE_DEBUG_POSTFIX@) -# search for the boost version assimp was compiled with -#set(Boost_USE_MULTITHREAD ON) -#set(Boost_USE_STATIC_LIBS OFF) -#set(Boost_USE_STATIC_RUNTIME OFF) -#find_package(Boost ${ASSIMP_Boost_VERSION} EXACT COMPONENTS thread date_time) -#if(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0") -# set( ASSIMP_INCLUDE_DIRS "${ASSIMP_INCLUDE_DIRS}" ${Boost_INCLUDE_DIRS}) -#else(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0") -# message(WARNING "Failed to find Boost ${ASSIMP_Boost_VERSION} necessary for assimp") -#endif(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0") - -# the boost version assimp was compiled with -set( ASSIMP_Boost_VERSION "@Boost_MAJOR_VERSION@.@Boost_MINOR_VERSION@") - # for compatibility with pkg-config set(ASSIMP_CFLAGS_OTHER "${ASSIMP_CXX_FLAGS}") set(ASSIMP_LDFLAGS_OTHER "${ASSIMP_LINK_FLAGS}") @@ -74,7 +56,6 @@ MARK_AS_ADVANCED( ASSIMP_LINK_FLAGS ASSIMP_INCLUDE_DIRS ASSIMP_LIBRARIES - ASSIMP_Boost_VERSION ASSIMP_CFLAGS_OTHER ASSIMP_LDFLAGS_OTHER ASSIMP_LIBRARY_SUFFIX From 35f4e7101a2ac88e3478156be77dd083fc64257b Mon Sep 17 00:00:00 2001 From: Edward Andrew <=ed.andrew95@gmail.com> Date: Mon, 2 Apr 2018 01:46:14 +0100 Subject: [PATCH 133/278] Fixed issue#1219. CalcTangentsProcess::ProcessMesh. --- code/CalcTangentsProcess.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/CalcTangentsProcess.cpp b/code/CalcTangentsProcess.cpp index cb0117aef..d77d70a5b 100644 --- a/code/CalcTangentsProcess.cpp +++ b/code/CalcTangentsProcess.cpp @@ -190,7 +190,7 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) float tx = meshTex[p2].x - meshTex[p0].x, ty = meshTex[p2].y - meshTex[p0].y; float dirCorrection = (tx * sy - ty * sx) < 0.0f ? -1.0f : 1.0f; // when t1, t2, t3 in same position in UV space, just use default UV direction. - if ( 0 == sx && 0 ==sy && 0 == tx && 0 == ty ) { + if ( sx * ty == sy * tx ) { sx = 0.0; sy = 1.0; tx = 1.0; ty = 0.0; } From 4d662c42b3f984b68b4fc38c8807abff6ec7622b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 2 Apr 2018 10:27:05 +0200 Subject: [PATCH 134/278] Add check for SSE2-support. --- code/CMakeLists.txt | 2 ++ code/simd.cpp | 34 ++++++++++++++++++++++++++++++++++ code/simd.h | 5 +++++ test/CMakeLists.txt | 1 + test/unit/utAnim.cpp | 4 +--- 5 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 code/simd.cpp create mode 100644 code/simd.h diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 7ae1a7e63..d5d05db18 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -186,6 +186,8 @@ SET( Common_SRCS Bitmap.cpp Version.cpp CreateAnimMesh.cpp + simd.h + simd.cpp ) SOURCE_GROUP(Common FILES ${Common_SRCS}) diff --git a/code/simd.cpp b/code/simd.cpp new file mode 100644 index 000000000..e07398156 --- /dev/null +++ b/code/simd.cpp @@ -0,0 +1,34 @@ +#include "simd.h" + +namespace Assimp { + bool CPUSupportsSSE2() { +#if defined(__x86_64__) || defined(_M_X64) + //* x86_64 always has SSE2 instructions */ + return true; +#elif defined(__GNUC__) && defined(i386) + // for GCC x86 we check cpuid + unsigned int d; + __asm__( + "pushl %%ebx\n\t" + "cpuid\n\t" + "popl %%ebx\n\t" + : "=d" ( d ) + :"a" ( 1 ) ); + return ( d & 0x04000000 ) != 0; +#elif (defined(_MSC_VER) && defined(_M_IX86)) + // also check cpuid for MSVC x86 + unsigned int d; + __asm { + xor eax, eax + inc eax + push ebx + cpuid + pop ebx + mov d, edx + } + return ( d & 0x04000000 ) != 0; +#else + return false; +#endif + } +} diff --git a/code/simd.h b/code/simd.h new file mode 100644 index 000000000..d490cbe85 --- /dev/null +++ b/code/simd.h @@ -0,0 +1,5 @@ +#pragma once + +namespace Assimp { + bool CPUSupportsSSE2(); +} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 049dbcdd2..7c5ff3706 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -53,6 +53,7 @@ endif() LINK_DIRECTORIES( ${Assimp_BINARY_DIR} ${AssetImporter_BINARY_DIR}/lib ) SET( COMMON + unit/utSimd.cpp unit/utIOSystem.cpp unit/utIOStreamBuffer.cpp unit/utIssues.cpp diff --git a/test/unit/utAnim.cpp b/test/unit/utAnim.cpp index 04ee8c96d..40c840d7e 100644 --- a/test/unit/utAnim.cpp +++ b/test/unit/utAnim.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2018, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -106,4 +104,4 @@ TEST_F( utAnim, aiAnimationTest ) { ok = false; } EXPECT_TRUE( ok ); -} \ No newline at end of file +} From 7faf638cca1ea5f05680df812dd0445a828460fa Mon Sep 17 00:00:00 2001 From: Andy Maloney Date: Mon, 2 Apr 2018 14:41:02 -0400 Subject: [PATCH 135/278] Add links to some file format info in readme --- Readme.md | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/Readme.md b/Readme.md index 4ee8a0e90..c78a0c1c8 100644 --- a/Readme.md +++ b/Readme.md @@ -35,29 +35,29 @@ Please check our Wiki as well: https://github.com/assimp/assimp/wiki __Importers__: - 3D -- 3DS -- 3MF +- [3DS](https://en.wikipedia.org/wiki/.3ds) +- [3MF](https://en.wikipedia.org/wiki/3D_Manufacturing_Format) - AC -- AC3D +- [AC3D](https://en.wikipedia.org/wiki/AC3D) - ACC - AMJ - ASE - ASK - B3D -- BLEND (Blender) -- BVH -- COB +- [BLEND](https://en.wikipedia.org/wiki/.blend_(file_format)) +- [BVH](https://en.wikipedia.org/wiki/Biovision_Hierarchy) - CMS -- DAE/Collada -- DXF +- COB +- [DAE/Collada](https://en.wikipedia.org/wiki/COLLADA) +- [DXF](https://en.wikipedia.org/wiki/AutoCAD_DXF) - ENFF -- FBX -- glTF 1.0 + GLB -- glTF 2.0 +- [FBX](https://en.wikipedia.org/wiki/FBX) +- [glTF 1.0](https://en.wikipedia.org/wiki/GlTF#glTF_1.0) + GLB +- [glTF 2.0](https://en.wikipedia.org/wiki/GlTF#glTF_2.0) - HMB - IFC-STEP - IRR / IRRMESH -- LWO +- [LWO](https://en.wikipedia.org/wiki/LightWave_3D) - LWS - LXO - MD2 @@ -70,10 +70,10 @@ __Importers__: - MS3D - NDO - NFF -- OBJ -- OFF -- OGEX -- PLY +- [OBJ](https://en.wikipedia.org/wiki/Wavefront_.obj_file) +- [OFF](https://en.wikipedia.org/wiki/OFF_(file_format)) +- [OGEX](https://en.wikipedia.org/wiki/Open_Game_Engine_Exchange) +- [PLY](https://en.wikipedia.org/wiki/PLY_(file_format)) - PMX - PRJ - Q3O @@ -82,19 +82,19 @@ __Importers__: - SCN - SIB - SMD -- STL -- STP +- [STP](https://en.wikipedia.org/wiki/ISO_10303-21) +- [STL](https://en.wikipedia.org/wiki/STL_(file_format)) - TER - UC - VTA - X -- X3D +- [X3D](https://en.wikipedia.org/wiki/X3D) - XGL - ZGL Additionally, some formats are supported by dependency on non-free code or external SDKs (not built by default): -- C4D (https://github.com/assimp/assimp/wiki/Cinema4D-&-Melange) +- [C4D](https://en.wikipedia.org/wiki/Cinema_4D) (https://github.com/assimp/assimp/wiki/Cinema4D-&-Melange) __Exporters__: From 6147a4f50d7dd746b7955b97c00d1f1564342c59 Mon Sep 17 00:00:00 2001 From: James Carthew Date: Wed, 4 Apr 2018 08:08:28 +1000 Subject: [PATCH 136/278] Updated COB importer plugin to flip normals. --- code/COBLoader.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/code/COBLoader.cpp b/code/COBLoader.cpp index 793cbfe75..222088cbd 100644 --- a/code/COBLoader.cpp +++ b/code/COBLoader.cpp @@ -47,11 +47,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_COB_IMPORTER #include "COBLoader.h" #include "COBScene.h" - +#include "ConvertToLHProcess.h" #include #include #include - #include #include #include @@ -105,7 +104,7 @@ COBImporter::~COBImporter() bool COBImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const { const std::string& extension = GetExtension(pFile); - if (extension == "cob" || extension == "scn") { + if (extension == "cob" || extension == "scn" || extension == "COB" || extension == "SCN") { return true; } @@ -225,6 +224,9 @@ void COBImporter::InternReadFile( const std::string& pFile, } pScene->mRootNode = BuildNodes(*root.get(),scene,pScene); + //flip normals after import + FlipWindingOrderProcess flip; + flip.Execute( pScene ); } // ------------------------------------------------------------------------------------------------ @@ -1299,3 +1301,4 @@ void COBImporter::ReadUnit_Binary(COB::Scene& out, StreamReaderLE& reader, const #endif + From c232c4bfb328fa6762aecbd258b4d8fd795a1349 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 4 Apr 2018 16:32:18 +0200 Subject: [PATCH 137/278] Add missing file to fix the build. --- test/unit/utSimd.cpp | 57 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 test/unit/utSimd.cpp diff --git a/test/unit/utSimd.cpp b/test/unit/utSimd.cpp new file mode 100644 index 000000000..da1b19fce --- /dev/null +++ b/test/unit/utSimd.cpp @@ -0,0 +1,57 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2018, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#include "UnitTestPCH.h" + +#include "simd.h" + +using namespace ::Assimp; + +class utSimd : public ::testing::Test { +protected: + // empty +}; + +TEST_F( utSimd, SSE2SupportedTest ) { + bool isSupported; + + isSupported = CPUSupportsSSE2(); +} From 4254142575019cb567306ce58c310847bd6d5a56 Mon Sep 17 00:00:00 2001 From: James Carthew Date: Thu, 5 Apr 2018 06:37:18 +1000 Subject: [PATCH 138/278] Updated GLView to draw with white lighting after drawCoordSystem(). --- tools/assimp_qt_viewer/glview.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/assimp_qt_viewer/glview.cpp b/tools/assimp_qt_viewer/glview.cpp index 5b755d456..d30d0b5de 100644 --- a/tools/assimp_qt_viewer/glview.cpp +++ b/tools/assimp_qt_viewer/glview.cpp @@ -609,6 +609,7 @@ void CGLView::drawCoordSystem() { // Z, -Z qglColor(QColor(Qt::blue)), glVertex3f(0.0, 0.0, 0.0), glVertex3f(0.0, 0.0, 100000.0); qglColor(QColor(Qt::yellow)), glVertex3f(0.0, 0.0, 0.0), glVertex3f(0.0, 0.0, -100000.0); + qglColor(QColor(Qt::white)); glEnd(); } From 8cb25328cb4381d4d1d11627b5c6c9444e021cc3 Mon Sep 17 00:00:00 2001 From: James Carthew Date: Thu, 5 Apr 2018 17:50:30 +1000 Subject: [PATCH 139/278] committing all changes. --- code/3DSLoader.cpp | 4 ++-- tools/assimp_qt_viewer/glview.cpp | 29 ++++++++++++++++++++++++++- tools/assimp_qt_viewer/glview.hpp | 11 ++++++++-- tools/assimp_qt_viewer/mainwindow.cpp | 20 ++++++++++++++++++ tools/assimp_qt_viewer/mainwindow.hpp | 4 +++- tools/assimp_qt_viewer/mainwindow.ui | 22 +++++++++++++++++++- 6 files changed, 83 insertions(+), 7 deletions(-) diff --git a/code/3DSLoader.cpp b/code/3DSLoader.cpp index 92a64e3d8..bfe2bf6e5 100644 --- a/code/3DSLoader.cpp +++ b/code/3DSLoader.cpp @@ -71,7 +71,7 @@ static const aiImporterDesc desc = { 0, 0, 0, - "3ds prj" + "3ds prj 3DS PRJ" }; @@ -127,7 +127,7 @@ Discreet3DSImporter::~Discreet3DSImporter() { // Returns whether the class can handle the format of the given file. bool Discreet3DSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const { std::string extension = GetExtension(pFile); - if(extension == "3ds" || extension == "prj" ) { + if(extension == "3ds" || extension == "3DS" || extension == "prj"|| extension == "PRJ" ) { return true; } diff --git a/tools/assimp_qt_viewer/glview.cpp b/tools/assimp_qt_viewer/glview.cpp index d30d0b5de..a9a60a6fc 100644 --- a/tools/assimp_qt_viewer/glview.cpp +++ b/tools/assimp_qt_viewer/glview.cpp @@ -560,6 +560,30 @@ void CGLView::Enable_Textures(const bool pEnable) } } +void CGLView::Enable_Axes(const bool pEnable){ + if(pEnable) + { + this->mAxesEnabled = true; + } + else + { + this->mAxesEnabled = false; + } +} + +void CGLView::Enable_Reload_Textures(const bool pEnable) +{ + if(pEnable) + { + this->mReloadTexturesEnabled = true; +// this->mScene->ImportTextures(this->mScene->pScenePath); + } + else + { + this->mReloadTexturesEnabled = false; + } +} + /********************************************************************/ /*********************** Override functions ************************/ /********************************************************************/ @@ -630,7 +654,10 @@ void CGLView::paintGL() if ( mLightingEnabled ) { glDisable( GL_LIGHTING );///TODO: display list } - drawCoordSystem(); + if (this->mAxesEnabled == true) + { + drawCoordSystem(); + } glDisable(GL_COLOR_MATERIAL); if(mLightingEnabled) glEnable(GL_LIGHTING); diff --git a/tools/assimp_qt_viewer/glview.hpp b/tools/assimp_qt_viewer/glview.hpp index ecd7c6b0f..1c397f13f 100644 --- a/tools/assimp_qt_viewer/glview.hpp +++ b/tools/assimp_qt_viewer/glview.hpp @@ -75,7 +75,9 @@ private: }; public: - + bool mAxesEnabled = true; + // Textures + bool mReloadTexturesEnabled = false; // If true then textures will reload when the window is activated. /// \enum ELightType /// Type of light source. enum class ELightType { Directional, Point, Spot }; @@ -155,7 +157,6 @@ private: GLdouble mCamera_Viewport_AspectRatio;///< Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). // Lighting bool mLightingEnabled = false;///< If true then OpenGL lighting is enabled (glEnable(GL_LIGHTING)), if false - disabled. - // Textures ///TODO: map is goooood, but not for case when one image can be used in different materials with difference in: texture transformation, targeting of the /// texture (ambient or emission, or even height map), texture properties. QMap mTexture_IDMap;///< Map image filenames to textures ID's. @@ -306,6 +307,12 @@ public: /// \param [in] pEnable - if true then enable textures, false - disable textures. void Enable_Textures(const bool pEnable); + void Enable_Axes(const bool pEnable); + /// \fn void Enable_Textures(const bool pEnable) + /// Control textures drawing. + /// \param [in] pEnable - if true then enable textures, false - disable textures. + void Enable_Reload_Textures(const bool pEnable); + /********************************************************************/ /******************** Lighting control functions ********************/ /********************************************************************/ diff --git a/tools/assimp_qt_viewer/mainwindow.cpp b/tools/assimp_qt_viewer/mainwindow.cpp index acfc8e589..d7d809086 100644 --- a/tools/assimp_qt_viewer/mainwindow.cpp +++ b/tools/assimp_qt_viewer/mainwindow.cpp @@ -48,6 +48,7 @@ QTime time_begin = QTime::currentTime(); ui->cbxLighting->setChecked(true); mGLView->Lighting_Enable(); ui->cbxBBox->setChecked(false); mGLView->Enable_SceneBBox(false); ui->cbxTextures->setChecked(true); mGLView->Enable_Textures(true); + ui->cbxReloadTextures->setChecked(true); mGLView->Enable_Reload_Textures(false); // // Fill info labels // @@ -194,6 +195,13 @@ GLfloat step; /********************************************************************/ /********************** Constructor/Destructor **********************/ /********************************************************************/ +bool MainWindow::event(QEvent *e) +{ + if (e->type() == QEvent::WindowActivate && this->mGLView->mReloadTexturesEnabled == true) { + qInfo() << "Window Activated"; + } + return QWidget::event(e); +} MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), @@ -364,6 +372,18 @@ void MainWindow::on_cbxBBox_clicked(bool checked) mGLView->updateGL(); } +void MainWindow::on_cbxDrawAxes_clicked(bool checked) +{ + mGLView->Enable_Axes(checked); + mGLView->updateGL(); +} + +void MainWindow::on_cbxReloadTextures_clicked(bool checked) +{ + mGLView->Enable_Reload_Textures(checked); + mGLView->updateGL(); +} + void MainWindow::on_cbxTextures_clicked(bool checked) { mGLView->Enable_Textures(checked); diff --git a/tools/assimp_qt_viewer/mainwindow.hpp b/tools/assimp_qt_viewer/mainwindow.hpp index 350b37abf..da8a852ac 100644 --- a/tools/assimp_qt_viewer/mainwindow.hpp +++ b/tools/assimp_qt_viewer/mainwindow.hpp @@ -90,7 +90,7 @@ protected: /// \param [in] pEvent - pointer to event data. void keyPressEvent(QKeyEvent* pEvent) override; - + bool event(QEvent*); public: /********************************************************************/ @@ -133,4 +133,6 @@ private slots: void on_lstCamera_clicked(const QModelIndex &index); void on_cbxBBox_clicked(bool checked); void on_cbxTextures_clicked(bool checked); + void on_cbxDrawAxes_clicked(bool checked); + void on_cbxReloadTextures_clicked(bool checked); }; diff --git a/tools/assimp_qt_viewer/mainwindow.ui b/tools/assimp_qt_viewer/mainwindow.ui index 105a470e0..9b139bafd 100644 --- a/tools/assimp_qt_viewer/mainwindow.ui +++ b/tools/assimp_qt_viewer/mainwindow.ui @@ -7,7 +7,7 @@ 0 0 641 - 734 + 778 @@ -501,6 +501,23 @@ + + + + Show Axes + + + true + + + + + + + Live Reload Textures + + + @@ -513,4 +530,7 @@ + + installEventFilter() + From 08ddd5c296589fe398eb851a7aa9f34025f6c5c5 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 6 Apr 2018 10:53:32 +0200 Subject: [PATCH 140/278] Export missig symbols. --- code/simd.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ code/simd.h | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 90 insertions(+), 2 deletions(-) diff --git a/code/simd.cpp b/code/simd.cpp index e07398156..9c86cb970 100644 --- a/code/simd.cpp +++ b/code/simd.cpp @@ -1,3 +1,45 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2018, assimp team + + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #include "simd.h" namespace Assimp { diff --git a/code/simd.h b/code/simd.h index d490cbe85..8fe2bb851 100644 --- a/code/simd.h +++ b/code/simd.h @@ -1,5 +1,51 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2018, assimp team + + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ #pragma once +#include + namespace Assimp { - bool CPUSupportsSSE2(); -} + +bool ASSIMP_API CPUSupportsSSE2(); + +} // Namespace Assimp From d17cf76c8576592572f9a6093648c176df840fa2 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 6 Apr 2018 11:16:52 +0200 Subject: [PATCH 141/278] Fix compiler warning in unit test: unused variable. --- test/unit/utSimd.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/unit/utSimd.cpp b/test/unit/utSimd.cpp index da1b19fce..33358c0da 100644 --- a/test/unit/utSimd.cpp +++ b/test/unit/utSimd.cpp @@ -54,4 +54,9 @@ TEST_F( utSimd, SSE2SupportedTest ) { bool isSupported; isSupported = CPUSupportsSSE2(); + if ( isSupported ) { + std::cout << "Supported" << std::endl; + } else { + std::cout << "Not supported" << std::endl; + } } From 32b466941beb1d041eaad84cd2be0b697d31fcfb Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 6 Apr 2018 12:01:22 +0200 Subject: [PATCH 142/278] Add missig docs and fix some small review findings. --- code/ScenePrivate.h | 32 ++++++++++----- code/simd.cpp | 54 +++++++++++++------------- code/simd.h | 2 + test/unit/AbstractImportExportBase.cpp | 2 +- 4 files changed, 53 insertions(+), 37 deletions(-) diff --git a/code/ScenePrivate.h b/code/ScenePrivate.h index a09d8784b..6a44def2c 100644 --- a/code/ScenePrivate.h +++ b/code/ScenePrivate.h @@ -42,22 +42,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file Stuff to deal with aiScene::mPrivate */ +#pragma once #ifndef AI_SCENEPRIVATE_H_INCLUDED #define AI_SCENEPRIVATE_H_INCLUDED #include -namespace Assimp { +namespace Assimp { +// Forward declarations class Importer; struct ScenePrivateData { - ScenePrivateData() - : mOrigImporter() - , mPPStepsApplied() - , mIsCopy() - {} + : mOrigImporter( nullptr ) + , mPPStepsApplied( 0 ) + , mIsCopy( false ) { + // empty + } // Importer that originally loaded the scene though the C-API // If set, this object is owned by this private data instance. @@ -75,14 +77,24 @@ struct ScenePrivateData { }; // Access private data stored in the scene -inline ScenePrivateData* ScenePriv(aiScene* in) { +inline +ScenePrivateData* ScenePriv(aiScene* in) { + ai_assert( nullptr != in ); + if ( nullptr == in ) { + return nullptr; + } return static_cast(in->mPrivate); } -inline const ScenePrivateData* ScenePriv(const aiScene* in) { +inline +const ScenePrivateData* ScenePriv(const aiScene* in) { + ai_assert( nullptr != in ); + if ( nullptr == in ) { + return nullptr; + } return static_cast(in->mPrivate); } -} +} // Namespace Assimp -#endif +#endif // AI_SCENEPRIVATE_H_INCLUDED diff --git a/code/simd.cpp b/code/simd.cpp index 9c86cb970..bd951bffa 100644 --- a/code/simd.cpp +++ b/code/simd.cpp @@ -43,34 +43,36 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "simd.h" namespace Assimp { - bool CPUSupportsSSE2() { + +bool CPUSupportsSSE2() { #if defined(__x86_64__) || defined(_M_X64) - //* x86_64 always has SSE2 instructions */ - return true; + //* x86_64 always has SSE2 instructions */ + return true; #elif defined(__GNUC__) && defined(i386) - // for GCC x86 we check cpuid - unsigned int d; - __asm__( - "pushl %%ebx\n\t" - "cpuid\n\t" - "popl %%ebx\n\t" - : "=d" ( d ) - :"a" ( 1 ) ); - return ( d & 0x04000000 ) != 0; + // for GCC x86 we check cpuid + unsigned int d; + __asm__( + "pushl %%ebx\n\t" + "cpuid\n\t" + "popl %%ebx\n\t" + : "=d" ( d ) + :"a" ( 1 ) ); + return ( d & 0x04000000 ) != 0; #elif (defined(_MSC_VER) && defined(_M_IX86)) - // also check cpuid for MSVC x86 - unsigned int d; - __asm { - xor eax, eax - inc eax - push ebx - cpuid - pop ebx - mov d, edx - } - return ( d & 0x04000000 ) != 0; -#else - return false; -#endif + // also check cpuid for MSVC x86 + unsigned int d; + __asm { + xor eax, eax + inc eax + push ebx + cpuid + pop ebx + mov d, edx } + return ( d & 0x04000000 ) != 0; +#else + return false; +#endif } + +} // Namespace Assimp diff --git a/code/simd.h b/code/simd.h index 8fe2bb851..19117569d 100644 --- a/code/simd.h +++ b/code/simd.h @@ -46,6 +46,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { +/// @brief Checks if the platform supports SSE2 optimization +/// @return true, if SSE2 is supported. false if SSE2 is not supported. bool ASSIMP_API CPUSupportsSSE2(); } // Namespace Assimp diff --git a/test/unit/AbstractImportExportBase.cpp b/test/unit/AbstractImportExportBase.cpp index f75ba4ea2..c09ec0fd7 100644 --- a/test/unit/AbstractImportExportBase.cpp +++ b/test/unit/AbstractImportExportBase.cpp @@ -45,5 +45,5 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace ::Assimp; AbstractImportExportBase::~AbstractImportExportBase() { - // empty + // empty } From 3bd80a2537b6cfeecec7852b578ede1234e5eb38 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 6 Apr 2018 12:05:30 +0200 Subject: [PATCH 143/278] closes https://github.com/assimp/assimp/issues/1881: make template-based get and put in streamreader/writer public. --- include/assimp/StreamReader.h | 2 +- include/assimp/StreamWriter.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/include/assimp/StreamReader.h b/include/assimp/StreamReader.h index 90cc65fee..3fab00ad2 100644 --- a/include/assimp/StreamReader.h +++ b/include/assimp/StreamReader.h @@ -283,7 +283,6 @@ public: return *this; } -private: // --------------------------------------------------------------------- /** Generic read method. ByteSwap::Swap(T*) *must* be defined */ template @@ -300,6 +299,7 @@ private: return f; } +private: // --------------------------------------------------------------------- void InternBegin() { if (!stream) { diff --git a/include/assimp/StreamWriter.h b/include/assimp/StreamWriter.h index 5ce3b172b..deb35fb4d 100644 --- a/include/assimp/StreamWriter.h +++ b/include/assimp/StreamWriter.h @@ -255,8 +255,6 @@ public: cursor = new_cursor; } -private: - // --------------------------------------------------------------------- /** Generic write method. ByteSwap::Swap(T*) *must* be defined */ template From 0a3fb04b041ba5723a74792959cdd06d6ee05ea5 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 6 Apr 2018 16:23:59 +0200 Subject: [PATCH 144/278] Update ScenePrivate.h add missing header --- code/ScenePrivate.h | 1 + 1 file changed, 1 insertion(+) diff --git a/code/ScenePrivate.h b/code/ScenePrivate.h index 6a44def2c..50959f455 100644 --- a/code/ScenePrivate.h +++ b/code/ScenePrivate.h @@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_SCENEPRIVATE_H_INCLUDED #define AI_SCENEPRIVATE_H_INCLUDED +#include #include namespace Assimp { From 183224f045ba93f9e93d7a8c5e880aa38feaaf22 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 6 Apr 2018 20:51:07 +0200 Subject: [PATCH 145/278] closes https://github.com/assimp/assimp/issues/1621: add file check for dxf file without extensions. --- code/DXFLoader.cpp | 9 +++++++-- doc/dox.h | 48 ++++------------------------------------------ 2 files changed, 11 insertions(+), 46 deletions(-) diff --git a/code/DXFLoader.cpp b/code/DXFLoader.cpp index 9a13caa33..e4529097d 100644 --- a/code/DXFLoader.cpp +++ b/code/DXFLoader.cpp @@ -119,9 +119,14 @@ DXFImporter::~DXFImporter() // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool DXFImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const +bool DXFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const { - return SimpleExtensionCheck(pFile,"dxf"); + if ( checkSig ) { + return SimpleExtensionCheck(pFile,"dxf"); + } else { + static const char *pTokens[] = { "SECTION", "HEADER", "ENDSEC", "BLOCKS" }; + return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 4 ); + } } // ------------------------------------------------------------------------------------------------ diff --git a/doc/dox.h b/doc/dox.h index 5c6de51f1..ece3e31d9 100644 --- a/doc/dox.h +++ b/doc/dox.h @@ -206,56 +206,16 @@ the library files. Alternatively you can simply add the assimp project to your p your solution. -@section use_noboost Building without boost. - -The Boost-Workaround consists of dummy replacements for some boost utility templates. Currently there are replacements for - - - boost.scoped_ptr - - boost.scoped_array - - boost.format - - boost.random - - boost.common_factor - - boost.foreach - - boost.tuple - - boost.make_shared - -These implementations are very limited and are not intended for use outside assimp. A compiler -with full support for partial template specializations is required. To enable the workaround, put the following in -your compiler's list of predefined macros: -@code -#define ASSIMP_BUILD_BOOST_WORKAROUND -@endcode -
-If you're working with the provided solutions for Visual Studio use the -noboost build configs.
- -assimp_BUILD_BOOST_WORKAROUND implies assimp_BUILD_SINGLETHREADED.
-See the @ref assimp_st section -for more details. - - - @section assimp_dll Windows DLL Build -assimp can be built as DLL. You just need to select a -dll config from the list of project -configs and you're fine. +The Assimp-package can be built as DLL. You just need to run the default cmake run. -NOTE: Theoretically, assimp-dll can be used with multithreaded (non-dll) runtime libraries, -as long as you don't utilize any non-public stuff from the code folder. However, if you happen -to encounter *very* strange problems, try changing the runtime to Multithreaded (Debug) DLL. -@section assimp_stlport Building against STLport +@section assimp static lib -STLport is a free, fast and secure STL replacement that works with -all major compilers and platforms. To get it, download the latest release from -. -Usually you'll just need to run 'configure' + a makefile (see their README for more details). -Don't miss to add /stlport to your compiler's default include paths - prior -to the directory where your compiler vendor's headers lie. Do the same for /lib and -recompile assimp. To ensure you're really building against STLport see aiGetCompileFlags(). -
-In our testing, STLport builds tend to be a bit faster than builds against Microsoft's -C++ Standard Library. +The Assimp-package can be build as a static library as well. Do do so just set the configuration variable BUILD_SHARED_LIBS +to off during the cmake run. */ From c41d459e212d151c37d2eccc5b43e63cd4bac349 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 8 Apr 2018 21:27:18 +0200 Subject: [PATCH 146/278] add missing constructor to ensure RTTI --- code/Importer.cpp | 5 +---- code/Importer.h | 30 ++++++++++++++++++++++++------ 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/code/Importer.cpp b/code/Importer.cpp index 6422ca6d0..6f9b47562 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -147,10 +147,7 @@ void AllocateFromAssimpHeap::operator delete[] ( void* data) { // ------------------------------------------------------------------------------------------------ // Importer constructor. Importer::Importer() - : pimpl( NULL ) { - // allocate the pimpl first - pimpl = new ImporterPimpl(); - + : pimpl( new ImporterPimpl ) { pimpl->mScene = NULL; pimpl->mErrorString = ""; diff --git a/code/Importer.h b/code/Importer.h index d15df2f85..870638631 100644 --- a/code/Importer.h +++ b/code/Importer.h @@ -68,10 +68,8 @@ namespace Assimp { * std::vector and std::map in the public headers. Furthermore we are dropping * any STL interface problems caused by mismatching STL settings. All * size calculation are now done by us, not the app heap. */ -class ImporterPimpl -{ +class ImporterPimpl { public: - // Data type to store the key hash typedef unsigned int KeyType; @@ -82,8 +80,6 @@ public: typedef std::map StringPropertyMap; typedef std::map MatrixPropertyMap; -public: - /** IO handler to use for all file accesses. */ IOSystem* mIOHandler; bool mIsDefaultHandler; @@ -117,12 +113,34 @@ public: MatrixPropertyMap mMatrixProperties; /** Used for testing - extra verbose mode causes the ValidateDataStructure-Step - * to be executed before and after every single postprocess step */ + * to be executed before and after every single post-process step */ bool bExtraVerbose; /** Used by post-process steps to share data */ SharedPostProcessInfo* mPPShared; + + /// The default class constructor. + ImporterPimpl(); }; + +inline +ImporterPimpl::ImporterPimpl() +: mIOHandler( nullptr ) +, mIsDefaultHandler( false ) +, mProgressHandler( nullptr ) +, mIsDefaultProgressHandler( false ) +, mImporter() +, mPostProcessingSteps() +, mScene( nullptr ) +, mErrorString() +, mIntProperties() +, mFloatProperties() +, mStringProperties() +, mMatrixProperties() +, bExtraVerbose( false ) +, mPPShared( nullptr ) { + // empty +} //! @endcond From 9ca32b2373a7da94cc940f0603fc3aad51b09919 Mon Sep 17 00:00:00 2001 From: kimkulling Date: Wed, 11 Apr 2018 17:04:49 +0200 Subject: [PATCH 147/278] closes https://github.com/assimp/assimp/issues/1894: use mesh name to name exported obj node. --- code/ObjExporter.cpp | 8 ++++++- code/OptimizeGraph.cpp | 54 ++++++++++++++++++------------------------ 2 files changed, 30 insertions(+), 32 deletions(-) diff --git a/code/ObjExporter.cpp b/code/ObjExporter.cpp index d08b5f859..6cd69f402 100644 --- a/code/ObjExporter.cpp +++ b/code/ObjExporter.cpp @@ -439,8 +439,14 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4 void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent) { const aiMatrix4x4& mAbs = mParent * nd->mTransformation; + aiMesh *cm( nullptr ); for(unsigned int i = 0; i < nd->mNumMeshes; ++i) { - AddMesh(nd->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs); + cm = pScene->mMeshes[nd->mMeshes[i]]; + if (nullptr != cm) { + AddMesh(cm->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs); + } else { + AddMesh(nd->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs); + } } for(unsigned int i = 0; i < nd->mNumChildren; ++i) { diff --git a/code/OptimizeGraph.cpp b/code/OptimizeGraph.cpp index 5a2607d4f..7835c3f01 100644 --- a/code/OptimizeGraph.cpp +++ b/code/OptimizeGraph.cpp @@ -73,28 +73,28 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer OptimizeGraphProcess::OptimizeGraphProcess() - : mScene() - , nodes_in() - , nodes_out() - , count_merged() -{} +: mScene() +, nodes_in() +, nodes_out() +, count_merged() { + // empty +} // ------------------------------------------------------------------------------------------------ // Destructor, private as well -OptimizeGraphProcess::~OptimizeGraphProcess() -{} +OptimizeGraphProcess::~OptimizeGraphProcess() { + // empty +} // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool OptimizeGraphProcess::IsActive( unsigned int pFlags) const -{ +bool OptimizeGraphProcess::IsActive( unsigned int pFlags) const { return (0 != (pFlags & aiProcess_OptimizeGraph)); } // ------------------------------------------------------------------------------------------------ -// Setup properties for the postprocessing step -void OptimizeGraphProcess::SetupProperties(const Importer* pImp) -{ +// Setup properties for the post-processing step +void OptimizeGraphProcess::SetupProperties(const Importer* pImp) { // Get value of AI_CONFIG_PP_OG_EXCLUDE_LIST std::string tmp = pImp->GetPropertyString(AI_CONFIG_PP_OG_EXCLUDE_LIST,""); AddLockedNodeList(tmp); @@ -102,16 +102,14 @@ void OptimizeGraphProcess::SetupProperties(const Importer* pImp) // ------------------------------------------------------------------------------------------------ // Collect new children -void OptimizeGraphProcess::CollectNewChildren(aiNode* nd, std::list& nodes) -{ +void OptimizeGraphProcess::CollectNewChildren(aiNode* nd, std::list& nodes) { nodes_in += nd->mNumChildren; // Process children std::list child_nodes; for (unsigned int i = 0; i < nd->mNumChildren; ++i) { - CollectNewChildren(nd->mChildren[i],child_nodes); - nd->mChildren[i] = NULL; + nd->mChildren[i] = nullptr; } // Check whether we need this node; if not we can replace it by our own children (warn, danger of incest). @@ -130,13 +128,11 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode* nd, std::list& no if (nd->mNumMeshes || !child_nodes.empty()) { nodes.push_back(nd); - } - else { + } else { delete nd; /* bye, node */ return; } - } - else { + } else { // Retain our current position in the hierarchy nodes.push_back(nd); @@ -160,14 +156,11 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode* nd, std::list& no } } if (n == child->mNumMeshes) { - if (!join_master) { join_master = child; inv = join_master->mTransformation; inv.Inverse(); - } - else { - + } else { child->mTransformation = inv * child->mTransformation ; join.push_back(child); @@ -227,9 +220,10 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode* nd, std::list& no delete[] nd->mChildren; - if (!child_nodes.empty()) + if (!child_nodes.empty()) { nd->mChildren = new aiNode*[child_nodes.size()]; - else nd->mChildren = NULL; + } + else nd->mChildren = nullptr; } nd->mNumChildren = static_cast(child_nodes.size()); @@ -246,9 +240,8 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode* nd, std::list& no } // ------------------------------------------------------------------------------------------------ -// Execute the postprocessing step on the given scene -void OptimizeGraphProcess::Execute( aiScene* pScene) -{ +// Execute the post-processing step on the given scene +void OptimizeGraphProcess::Execute( aiScene* pScene) { DefaultLogger::get()->debug("OptimizeGraphProcess begin"); nodes_in = nodes_out = count_merged = 0; mScene = pScene; @@ -268,7 +261,6 @@ void OptimizeGraphProcess::Execute( aiScene* pScene) for (unsigned int i = 0; i < pScene->mNumAnimations; ++i) { for (unsigned int a = 0; a < pScene->mAnimations[i]->mNumChannels; ++a) { - aiNodeAnim* anim = pScene->mAnimations[i]->mChannels[a]; locked.insert(AI_OG_GETKEY(anim->mNodeName)); } @@ -349,7 +341,7 @@ void OptimizeGraphProcess::Execute( aiScene* pScene) } // ------------------------------------------------------------------------------------------------ -// Buidl a LUT of all instanced meshes +// Build a LUT of all instanced meshes void OptimizeGraphProcess::FindInstancedMeshes (aiNode* pNode) { for (unsigned int i = 0; i < pNode->mNumMeshes;++i) { From da073f1270ef139c28c0c073edaf194e48488f10 Mon Sep 17 00:00:00 2001 From: kimkulling Date: Wed, 11 Apr 2018 17:22:31 +0200 Subject: [PATCH 148/278] closes https://github.com/assimp/assimp/issues/1893: fix mem leak in glft2Importer. --- code/glTF2Importer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 11dc57856..3aeb3151e 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -412,7 +412,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r) aim->mBitangents[i] = (aim->mNormals[i] ^ tangents[i].xyz) * tangents[i].w; } - delete tangents; + delete [] tangents; } } From 5319974fe17f5c02c7e44041c8432cd977b31d8a Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 11 Apr 2018 21:16:20 +0200 Subject: [PATCH 149/278] Use correct check to do a tokensearch. --- code/DXFLoader.cpp | 14 +++++++++----- test/unit/utDXFImporterExporter.cpp | 7 +++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/code/DXFLoader.cpp b/code/DXFLoader.cpp index e4529097d..c8aee18dd 100644 --- a/code/DXFLoader.cpp +++ b/code/DXFLoader.cpp @@ -119,14 +119,18 @@ DXFImporter::~DXFImporter() // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool DXFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const -{ - if ( checkSig ) { - return SimpleExtensionCheck(pFile,"dxf"); - } else { +bool DXFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const { + const std::string& extension = GetExtension( pFile ); + if ( extension == "dxf" ) { + return true; + } + + if ( extension.empty() || checkSig ) { static const char *pTokens[] = { "SECTION", "HEADER", "ENDSEC", "BLOCKS" }; return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 4 ); } + + return false; } // ------------------------------------------------------------------------------------------------ diff --git a/test/unit/utDXFImporterExporter.cpp b/test/unit/utDXFImporterExporter.cpp index 1cb23cccf..ee6f34ecd 100644 --- a/test/unit/utDXFImporterExporter.cpp +++ b/test/unit/utDXFImporterExporter.cpp @@ -62,3 +62,10 @@ public: TEST_F( utDXFImporterExporter, importDXFFromFileTest ) { EXPECT_TRUE( importerTest() ); } + +TEST_F( utDXFImporterExporter, importerWithoutExtensionTest ) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/DXF/lineTest", aiProcess_ValidateDataStructure ); + EXPECT_NE( nullptr, scene ); +} + From 42dcf8c14c19cf737aec0070ba1e21aa2b1da122 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 11 Apr 2018 23:11:13 +0200 Subject: [PATCH 150/278] Add missing test DXF-file. --- test/models/DXF/lineTest | 190 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 test/models/DXF/lineTest diff --git a/test/models/DXF/lineTest b/test/models/DXF/lineTest new file mode 100644 index 000000000..2e16f69fd --- /dev/null +++ b/test/models/DXF/lineTest @@ -0,0 +1,190 @@ +999 +VISION3D DXF +0 +SECTION +2 +HEADER +9 +$ACADVER +1 +AC1006 +9 +$INSBASE +10 +0.0 +20 +0.0 +30 +0.0 +9 +$EXTMIN +10 +0.0 +20 +0.0 +9 +$EXTMAX +10 +1000.0 +20 +1000.0 +9 +$LINMIN +10 +0.0 +20 +0.0 +9 +$LINMAX +10 +1000.0 +20 +1000.0 +0 +ENDSEC +0 +SECTION +2 +TABLES +0 +TABLE +2 +LTYPE +70 +1 +0 +LTYPE +2 +CONTINUOUS +70 +64 +3 +Solid line +72 +65 +73 +0 +40 +0.000000 +0 +ENDTAB +0 +TABLE +2 +LAYER +70 +6 +0 +LAYER +2 +1 +70 +64 +62 +7 +6 +CONTINUOUS +0 +ENDTAB +0 +TABLE +2 +STYLE +70 +0 +0 +ENDTAB +0 +ENDSEC +0 +SECTION +2 +BLOCKS +0 +ENDSEC +0 +SECTION +2 +ENTITIES +0 +3DFACE +8 +1 +62 +1 +10 +-0.5 +20 +-0.5 +30 +-0.5 +11 +-0.5 +21 +0.5 +31 +-0.5 +12 +0.5 +22 +0.5 +32 +-0.5 +13 +0.5 +23 +-0.5 +33 +-0.5 +0 +3DFACE +8 +1 +62 +1 +10 +-0.5 +20 +-0.5 +30 +-0.5 +11 +0.5 +21 +-0.5 +31 +-0.5 +12 +0 +22 +-0.5 +32 +0.5 +13 +0 +23 +-0.5 +33 +0.5 +0 +LINE +8 +1 +62 +1 +10 +0 +20 +-0.5 +30 +0.5 +11 +0 +21 +0.5 +31 +-0.5 +0 +ENDSEC +0 +EOF From e57394a772da96fdcbbbdffa3ab9c6950e0bb595 Mon Sep 17 00:00:00 2001 From: kimkulling Date: Thu, 12 Apr 2018 16:09:01 +0200 Subject: [PATCH 151/278] move log tools from blender to logger interface. --- code/BlenderModifier.cpp | 28 ----------- code/BlenderModifier.h | 57 ++++++++++----------- code/ColladaLoader.cpp | 5 +- include/assimp/Logger.hpp | 102 +++++++++++++++++++++++++------------- 4 files changed, 98 insertions(+), 94 deletions(-) diff --git a/code/BlenderModifier.cpp b/code/BlenderModifier.cpp index 9b73239ed..1f32ee410 100644 --- a/code/BlenderModifier.cpp +++ b/code/BlenderModifier.cpp @@ -70,34 +70,6 @@ static const fpCreateModifier creators[] = { NULL // sentinel }; -// ------------------------------------------------------------------------------------------------ -// just testing out some new macros to simplify logging -#define ASSIMP_LOG_WARN_F(string,...)\ - DefaultLogger::get()->warn((Formatter::format(string),__VA_ARGS__)) - -#define ASSIMP_LOG_ERROR_F(string,...)\ - DefaultLogger::get()->error((Formatter::format(string),__VA_ARGS__)) - -#define ASSIMP_LOG_DEBUG_F(string,...)\ - DefaultLogger::get()->debug((Formatter::format(string),__VA_ARGS__)) - -#define ASSIMP_LOG_INFO_F(string,...)\ - DefaultLogger::get()->info((Formatter::format(string),__VA_ARGS__)) - - -#define ASSIMP_LOG_WARN(string)\ - DefaultLogger::get()->warn(string) - -#define ASSIMP_LOG_ERROR(string)\ - DefaultLogger::get()->error(string) - -#define ASSIMP_LOG_DEBUG(string)\ - DefaultLogger::get()->debug(string) - -#define ASSIMP_LOG_INFO(string)\ - DefaultLogger::get()->info(string) - - // ------------------------------------------------------------------------------------------------ struct SharedModifierData : ElemBase { diff --git a/code/BlenderModifier.h b/code/BlenderModifier.h index 01d133499..cd34659c9 100644 --- a/code/BlenderModifier.h +++ b/code/BlenderModifier.h @@ -47,34 +47,39 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INCLUDED_AI_BLEND_MODIFIER_H #include "BlenderIntermediate.h" -#include namespace Assimp { namespace Blender { // ------------------------------------------------------------------------------------------- -/** Dummy base class for all blender modifiers. Modifiers are reused between imports, so - * they should be stateless and not try to cache model data. */ +/** + * Dummy base class for all blender modifiers. Modifiers are reused between imports, so + * they should be stateless and not try to cache model data. + */ // ------------------------------------------------------------------------------------------- -class BlenderModifier -{ +class BlenderModifier { public: + /** + * The class destructor, virtual. + */ virtual ~BlenderModifier() { // empty } -public: - // -------------------- - /** Check if *this* modifier is active, given a ModifierData& block.*/ + /** + * Check if *this* modifier is active, given a ModifierData& block. + */ virtual bool IsActive( const ModifierData& /*modin*/) { return false; } // -------------------- - /** Apply the modifier to a given output node. The original data used + /** + * Apply the modifier to a given output node. The original data used * to construct the node is given as well. Not called unless IsActive() - * was called and gave positive response. */ + * was called and gave positive response. + */ virtual void DoIt(aiNode& /*out*/, ConversionData& /*conv_data*/, const ElemBase& orig_modifier, @@ -86,14 +91,13 @@ public: } }; - // ------------------------------------------------------------------------------------------- -/** Manage all known modifiers and instance and apply them if necessary */ +/** + * Manage all known modifiers and instance and apply them if necessary + */ // ------------------------------------------------------------------------------------------- -class BlenderModifierShowcase -{ +class BlenderModifierShowcase { public: - // -------------------- /** Apply all requested modifiers provided we support them. */ void ApplyModifiers(aiNode& out, @@ -103,25 +107,18 @@ public: ); private: - TempArray< std::vector,BlenderModifier > cached_modifiers; }; - - - - -// MODIFIERS - - +// MODIFIERS ///////////////////////////////////////////////////////////////////////////////// // ------------------------------------------------------------------------------------------- -/** Mirror modifier. Status: implemented. */ +/** + * Mirror modifier. Status: implemented. + */ // ------------------------------------------------------------------------------------------- -class BlenderModifier_Mirror : public BlenderModifier -{ +class BlenderModifier_Mirror : public BlenderModifier { public: - // -------------------- virtual bool IsActive( const ModifierData& modin); @@ -137,8 +134,7 @@ public: // ------------------------------------------------------------------------------------------- /** Subdivision modifier. Status: dummy. */ // ------------------------------------------------------------------------------------------- -class BlenderModifier_Subdivision : public BlenderModifier -{ +class BlenderModifier_Subdivision : public BlenderModifier { public: // -------------------- @@ -153,6 +149,7 @@ public: ) ; }; +} +} -}} #endif // !INCLUDED_AI_BLEND_MODIFIER_H diff --git a/code/ColladaLoader.cpp b/code/ColladaLoader.cpp index 01ba1c400..4bb5f4521 100644 --- a/code/ColladaLoader.cpp +++ b/code/ColladaLoader.cpp @@ -47,13 +47,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER #include "ColladaLoader.h" +#include "ColladaParser.h" + #include #include #include #include #include +#include -#include "ColladaParser.h" #include #include #include @@ -63,7 +65,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "math.h" #include #include -#include using namespace Assimp; using namespace Assimp::Formatter; diff --git a/include/assimp/Logger.hpp b/include/assimp/Logger.hpp index 56516ca4d..303f841ce 100644 --- a/include/assimp/Logger.hpp +++ b/include/assimp/Logger.hpp @@ -46,7 +46,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef INCLUDED_AI_LOGGER_H #define INCLUDED_AI_LOGGER_H -#include "types.h" +#include +#include namespace Assimp { @@ -59,7 +60,7 @@ class LogStream; /** @brief CPP-API: Abstract interface for logger implementations. * Assimp provides a default implementation and uses it for almost all * logging stuff ('DefaultLogger'). This class defines just basic logging - * behaviour and is not of interest for you. Instead, take a look at #DefaultLogger. */ + * behavior and is not of interest for you. Instead, take a look at #DefaultLogger. */ class ASSIMP_API Logger #ifndef SWIG : public Intern::AllocateFromAssimpHeap @@ -71,8 +72,7 @@ public: /** @enum LogSeverity * @brief Log severity to describe the granularity of logging. */ - enum LogSeverity - { + enum LogSeverity { NORMAL, //!< Normal granularity of logging VERBOSE //!< Debug infos will be logged, too }; @@ -85,8 +85,7 @@ public: * A LogStream doesn't receive any messages of a specific type * if it doesn't specify the corresponding ErrorSeverity flag. */ - enum ErrorSeverity - { + enum ErrorSeverity { Debugging = 1, //!< Debug log message Info = 2, //!< Info log message Warn = 4, //!< Warn log message @@ -102,25 +101,25 @@ public: /** @brief Writes a debug message * @param message Debug message*/ void debug(const char* message); - inline void debug(const std::string &message); + void debug(const std::string &message); // ---------------------------------------------------------------------- /** @brief Writes a info message * @param message Info message*/ void info(const char* message); - inline void info(const std::string &message); + void info(const std::string &message); // ---------------------------------------------------------------------- /** @brief Writes a warning message * @param message Warn message*/ void warn(const char* message); - inline void warn(const std::string &message); + void warn(const std::string &message); // ---------------------------------------------------------------------- /** @brief Writes an error message * @param message Error message*/ void error(const char* message); - inline void error(const std::string &message); + void error(const std::string &message); // ---------------------------------------------------------------------- /** @brief Set a new log severity. @@ -159,15 +158,19 @@ public: unsigned int severity = Debugging | Err | Warn | Info) = 0; protected: - - /** Default constructor */ + /** + * Default constructor + */ Logger(); - /** Construction with a given log severity */ + /** + * Construction with a given log severity + */ explicit Logger(LogSeverity severity); // ---------------------------------------------------------------------- - /** @brief Called as a request to write a specific debug message + /** + * @brief Called as a request to write a specific debug message * @param message Debug message. Never longer than * MAX_LOG_MESSAGE_LENGTH characters (excluding the '0'). * @note The message string is only valid until the scope of @@ -176,7 +179,8 @@ protected: virtual void OnDebug(const char* message)= 0; // ---------------------------------------------------------------------- - /** @brief Called as a request to write a specific info message + /** + * @brief Called as a request to write a specific info message * @param message Info message. Never longer than * MAX_LOG_MESSAGE_LENGTH characters (ecxluding the '0'). * @note The message string is only valid until the scope of @@ -185,7 +189,8 @@ protected: virtual void OnInfo(const char* message) = 0; // ---------------------------------------------------------------------- - /** @brief Called as a request to write a specific warn message + /** + * @brief Called as a request to write a specific warn message * @param message Warn message. Never longer than * MAX_LOG_MESSAGE_LENGTH characters (exluding the '0'). * @note The message string is only valid until the scope of @@ -194,7 +199,8 @@ protected: virtual void OnWarn(const char* essage) = 0; // ---------------------------------------------------------------------- - /** @brief Called as a request to write a specific error message + /** + * @brief Called as a request to write a specific error message * @param message Error message. Never longer than * MAX_LOG_MESSAGE_LENGTH characters (exluding the '0'). * @note The message string is only valid until the scope of @@ -203,66 +209,94 @@ protected: virtual void OnError(const char* message) = 0; protected: - - //! Logger severity LogSeverity m_Severity; }; // ---------------------------------------------------------------------------------- // Default constructor -inline Logger::Logger() { +inline +Logger::Logger() { setLogSeverity(NORMAL); } // ---------------------------------------------------------------------------------- // Virtual destructor -inline Logger::~Logger() -{ +inline +Logger::~Logger() { + // empty } // ---------------------------------------------------------------------------------- // Construction with given logging severity -inline Logger::Logger(LogSeverity severity) { +inline +Logger::Logger(LogSeverity severity) { setLogSeverity(severity); } // ---------------------------------------------------------------------------------- // Log severity setter -inline void Logger::setLogSeverity(LogSeverity log_severity){ +inline +void Logger::setLogSeverity(LogSeverity log_severity){ m_Severity = log_severity; } // ---------------------------------------------------------------------------------- // Log severity getter -inline Logger::LogSeverity Logger::getLogSeverity() const { +inline +Logger::LogSeverity Logger::getLogSeverity() const { return m_Severity; } // ---------------------------------------------------------------------------------- -inline void Logger::debug(const std::string &message) -{ +inline +void Logger::debug(const std::string &message) { return debug(message.c_str()); } // ---------------------------------------------------------------------------------- -inline void Logger::error(const std::string &message) -{ +inline +void Logger::error(const std::string &message) { return error(message.c_str()); } // ---------------------------------------------------------------------------------- -inline void Logger::warn(const std::string &message) -{ +inline +void Logger::warn(const std::string &message) { return warn(message.c_str()); } // ---------------------------------------------------------------------------------- -inline void Logger::info(const std::string &message) -{ +inline +void Logger::info(const std::string &message) { return info(message.c_str()); } -// ---------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------------------------ +#define ASSIMP_LOG_WARN_F(string,...)\ + DefaultLogger::get()->warn((Formatter::format(string),__VA_ARGS__)) + +#define ASSIMP_LOG_ERROR_F(string,...)\ + DefaultLogger::get()->error((Formatter::format(string),__VA_ARGS__)) + +#define ASSIMP_LOG_DEBUG_F(string,...)\ + DefaultLogger::get()->debug((Formatter::format(string),__VA_ARGS__)) + +#define ASSIMP_LOG_INFO_F(string,...)\ + DefaultLogger::get()->info((Formatter::format(string),__VA_ARGS__)) + + +#define ASSIMP_LOG_WARN(string)\ + DefaultLogger::get()->warn(string) + +#define ASSIMP_LOG_ERROR(string)\ + DefaultLogger::get()->error(string) + +#define ASSIMP_LOG_DEBUG(string)\ + DefaultLogger::get()->debug(string) + +#define ASSIMP_LOG_INFO(string)\ + DefaultLogger::get()->info(string) + } // Namespace Assimp From f235646030ac312bfe87ca1ffe938b2723f29bfc Mon Sep 17 00:00:00 2001 From: Arkeon Date: Fri, 13 Apr 2018 09:36:01 +0200 Subject: [PATCH 152/278] Correction on Collada parser missing textures when the image is in CDATA --- code/ColladaParser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index d96ac0d39..31fbabe0e 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -3106,7 +3106,7 @@ const char* ColladaParser::TestTextContent() // read contents of the element if( !mReader->read() ) return NULL; - if( mReader->getNodeType() != irr::io::EXN_TEXT) + if( mReader->getNodeType() != irr::io::EXN_TEXT && mReader->getNodeType() != irr::io::EXN_CDATA) return NULL; // skip leading whitespace From 6ca8423e24978f35c3f2e7f833eb9b06dadd56c2 Mon Sep 17 00:00:00 2001 From: Leo Terziman Date: Wed, 18 Apr 2018 11:12:40 +0200 Subject: [PATCH 153/278] Improved memory footprint of IFC loading by avoiding keeping in cache duplicated indices. --- code/Importer/IFC/IFCGeometry.cpp | 26 ++++++++++++-------------- code/Importer/IFC/IFCLoader.cpp | 4 ++-- code/Importer/IFC/IFCUtil.h | 6 +++--- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/code/Importer/IFC/IFCGeometry.cpp b/code/Importer/IFC/IFCGeometry.cpp index ba9098b6f..d49e5cb01 100644 --- a/code/Importer/IFC/IFCGeometry.cpp +++ b/code/Importer/IFC/IFCGeometry.cpp @@ -728,7 +728,7 @@ void ProcessSweptAreaSolid(const Schema_2x3::IfcSweptAreaSolid& swept, TempMesh& } // ------------------------------------------------------------------------------------------------ -bool ProcessGeometricItem(const Schema_2x3::IfcRepresentationItem& geo, unsigned int matid, std::vector& mesh_indices, +bool ProcessGeometricItem(const Schema_2x3::IfcRepresentationItem& geo, unsigned int matid, std::set& mesh_indices, ConversionData& conv) { bool fix_orientation = false; @@ -810,7 +810,7 @@ bool ProcessGeometricItem(const Schema_2x3::IfcRepresentationItem& geo, unsigned aiMesh* const mesh = meshtmp->ToMesh(); if(mesh) { mesh->mMaterialIndex = matid; - mesh_indices.push_back(static_cast(conv.meshes.size())); + mesh_indices.insert(static_cast(conv.meshes.size())); conv.meshes.push_back(mesh); return true; } @@ -818,33 +818,31 @@ bool ProcessGeometricItem(const Schema_2x3::IfcRepresentationItem& geo, unsigned } // ------------------------------------------------------------------------------------------------ -void AssignAddedMeshes(std::vector& mesh_indices,aiNode* nd, +void AssignAddedMeshes(std::set& mesh_indices,aiNode* nd, ConversionData& /*conv*/) { if (!mesh_indices.empty()) { + std::set::const_iterator it = mesh_indices.cbegin(); + std::set::const_iterator end = mesh_indices.cend(); - // make unique - std::sort(mesh_indices.begin(),mesh_indices.end()); - std::vector::iterator it_end = std::unique(mesh_indices.begin(),mesh_indices.end()); - - nd->mNumMeshes = static_cast(std::distance(mesh_indices.begin(),it_end)); + nd->mNumMeshes = static_cast(mesh_indices.size()); nd->mMeshes = new unsigned int[nd->mNumMeshes]; - for(unsigned int i = 0; i < nd->mNumMeshes; ++i) { - nd->mMeshes[i] = mesh_indices[i]; + for(unsigned int i = 0; it != end && i < nd->mNumMeshes; ++i, ++it) { + nd->mMeshes[i] = *it; } } } // ------------------------------------------------------------------------------------------------ bool TryQueryMeshCache(const Schema_2x3::IfcRepresentationItem& item, - std::vector& mesh_indices, unsigned int mat_index, + std::set& mesh_indices, unsigned int mat_index, ConversionData& conv) { ConversionData::MeshCacheIndex idx(&item, mat_index); ConversionData::MeshCache::const_iterator it = conv.cached_meshes.find(idx); if (it != conv.cached_meshes.end()) { - std::copy((*it).second.begin(),(*it).second.end(),std::back_inserter(mesh_indices)); + std::copy((*it).second.begin(),(*it).second.end(),std::inserter(mesh_indices, mesh_indices.end())); return true; } return false; @@ -852,7 +850,7 @@ bool TryQueryMeshCache(const Schema_2x3::IfcRepresentationItem& item, // ------------------------------------------------------------------------------------------------ void PopulateMeshCache(const Schema_2x3::IfcRepresentationItem& item, - const std::vector& mesh_indices, unsigned int mat_index, + const std::set& mesh_indices, unsigned int mat_index, ConversionData& conv) { ConversionData::MeshCacheIndex idx(&item, mat_index); @@ -861,7 +859,7 @@ void PopulateMeshCache(const Schema_2x3::IfcRepresentationItem& item, // ------------------------------------------------------------------------------------------------ bool ProcessRepresentationItem(const Schema_2x3::IfcRepresentationItem& item, unsigned int matid, - std::vector& mesh_indices, + std::set& mesh_indices, ConversionData& conv) { // determine material diff --git a/code/Importer/IFC/IFCLoader.cpp b/code/Importer/IFC/IFCLoader.cpp index 9faf68cbb..a40eedc1d 100644 --- a/code/Importer/IFC/IFCLoader.cpp +++ b/code/Importer/IFC/IFCLoader.cpp @@ -435,7 +435,7 @@ bool ProcessMappedItem(const Schema_2x3::IfcMappedItem& mapped, aiNode* nd_src, msrc = m*msrc; - std::vector meshes; + std::set meshes; const size_t old_openings = conv.collect_openings ? conv.collect_openings->size() : 0; if (conv.apply_openings) { IfcMatrix4 minv = msrc; @@ -550,7 +550,7 @@ void ProcessProductRepresentation(const Schema_2x3::IfcProduct& el, aiNode* nd, // extract Color from metadata, if present unsigned int matid = ProcessMaterials( el.GetID(), std::numeric_limits::max(), conv, false); - std::vector meshes; + std::set meshes; // we want only one representation type, so bring them in a suitable order (i.e try those // that look as if we could read them quickly at first). This way of reading diff --git a/code/Importer/IFC/IFCUtil.h b/code/Importer/IFC/IFCUtil.h index 479772d89..194206d4b 100644 --- a/code/Importer/IFC/IFCUtil.h +++ b/code/Importer/IFC/IFCUtil.h @@ -205,7 +205,7 @@ struct ConversionData bool operator == (const MeshCacheIndex& o) const { return item == o.item && matindex == o.matindex; } bool operator < (const MeshCacheIndex& o) const { return item < o.item || (item == o.item && matindex < o.matindex); } }; - typedef std::map > MeshCache; + typedef std::map > MeshCache; MeshCache cached_meshes; typedef std::map MaterialCache; @@ -281,8 +281,8 @@ unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionDat // IFCGeometry.cpp IfcMatrix3 DerivePlaneCoordinateSpace(const TempMesh& curmesh, bool& ok, IfcVector3& norOut); -bool ProcessRepresentationItem(const Schema_2x3::IfcRepresentationItem& item, unsigned int matid, std::vector& mesh_indices, ConversionData& conv); -void AssignAddedMeshes(std::vector& mesh_indices,aiNode* nd,ConversionData& /*conv*/); +bool ProcessRepresentationItem(const Schema_2x3::IfcRepresentationItem& item, unsigned int matid, std::set& mesh_indices, ConversionData& conv); +void AssignAddedMeshes(std::set& mesh_indices,aiNode* nd,ConversionData& /*conv*/); void ProcessSweptAreaSolid(const Schema_2x3::IfcSweptAreaSolid& swept, TempMesh& meshout, ConversionData& conv); From c797f16b0ed322d7c483906aaf821c809bee26fb Mon Sep 17 00:00:00 2001 From: Leo Terziman Date: Wed, 18 Apr 2018 11:53:49 +0200 Subject: [PATCH 154/278] In IFC, fixed parser to avoid interpretation of '##' in string as identifiers --- code/Importer/IFC/STEPFileReader.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/code/Importer/IFC/STEPFileReader.cpp b/code/Importer/IFC/STEPFileReader.cpp index ca02f7626..ba33f3928 100644 --- a/code/Importer/IFC/STEPFileReader.cpp +++ b/code/Importer/IFC/STEPFileReader.cpp @@ -492,10 +492,17 @@ STEP::LazyObject::LazyObject(DB& db, uint64_t id,uint64_t /*line*/, const char* --skip_depth; } - if (skip_depth >= 1 && *a=='#') { - const char* tmp; - const int64_t num = static_cast( strtoul10_64(a+1,&tmp) ); - db.MarkRef(num,id); + if (skip_depth >= 1 && *a=='#') { + if (*(a + 1) != '#') + { + const char* tmp; + const int64_t num = static_cast(strtoul10_64(a + 1, &tmp)); + db.MarkRef(num, id); + } + else + { + ++a; + } } ++a; } From f2833539d750a9705203bc8571fa45eb3ec264ae Mon Sep 17 00:00:00 2001 From: kimkulling Date: Thu, 19 Apr 2018 08:52:21 +0200 Subject: [PATCH 155/278] closes https://github.com/assimp/assimp/issues/1784: change so.name to keep track of the minor version of the lib. --- CMakeLists.txt | 6 +++--- code/glTF2Importer.cpp | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 83e1be081..add601d1b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -457,7 +457,7 @@ INSTALL( FILES "${PROJECT_BINARY_DIR}/assimp.pc" DESTINATION ${ASSIMP_LIB_INSTAL IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES) # Packing information - SET(CPACK_PACKAGE_NAME "assimp{ASSIMP_VERSION_MAJOR}") + SET(CPACK_PACKAGE_NAME "assimp{ASSIMP_VERSION_MAJOR}.{ASSIMP_VERSION_MINOR}") SET(CPACK_PACKAGE_CONTACT "" CACHE STRING "Package maintainer and PGP signer.") SET(CPACK_PACKAGE_VENDOR "https://github.com/assimp") SET(CPACK_PACKAGE_DISPLAY_NAME "Assimp ${ASSIMP_VERSION}") @@ -487,8 +487,8 @@ IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES) SET(CPACK_DEBIAN_PACKAGE_SECTION "libs" ) SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_COMPONENTS_ALL}") SET(CPACK_DEBIAN_PACKAGE_SUGGESTS) - SET(CPACK_DEBIAN_PACKAGE_NAME "assimp") - SET(CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES contrib/cppunit-1.12.1 contrib/cppunit_note.txt contrib/zlib workspaces test doc obj samples packaging) + set(cPACK_DEBIAN_PACKAGE_NAME "assimp") + SET(CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES contrib/gtest contrib/zlib workspaces test doc obj samples packaging) SET(CPACK_DEBIAN_PACKAGE_SOURCE_COPY svn export --force) SET(CPACK_DEBIAN_CHANGELOG) execute_process(COMMAND lsb_release -is diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 3aeb3151e..2bcf8b5de 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -396,8 +396,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r) // only extract tangents if normals are present if (attr.tangent.size() > 0 && attr.tangent[0]) { // generate bitangents from normals and tangents according to spec - struct Tangent - { + struct Tangent { aiVector3D xyz; ai_real w; } *tangents = nullptr; From 066349f36b0879208b67cc3c6b40c84d909a1b55 Mon Sep 17 00:00:00 2001 From: kimkulling Date: Thu, 19 Apr 2018 16:48:43 +0200 Subject: [PATCH 156/278] Add usage of log macros. --- code/3DSConverter.cpp | 18 ++++++------- code/3DSExporter.cpp | 2 +- code/3DSLoader.cpp | 40 ++++++++++++++-------------- code/ACLoader.cpp | 38 +++++++++++++------------- code/ASELoader.cpp | 16 +++++------ code/ASEParser.cpp | 26 +++++++++--------- code/B3DImporter.cpp | 2 +- code/BaseImporter.cpp | 50 +++++++++++++++++------------------ code/BaseProcess.cpp | 2 +- code/BlenderDNA.cpp | 9 +++---- code/BlenderDNA.h | 2 +- code/BlenderDNA.inl | 4 +-- code/BlenderLoader.cpp | 4 +-- code/BlenderModifier.h | 2 +- code/COBLoader.cpp | 8 +++--- code/ColladaLoader.cpp | 33 +++++++++++------------ code/ColladaParser.cpp | 32 +++++++++++----------- code/D3MFImporter.cpp | 2 +- code/D3MFOpcPackage.cpp | 2 +- code/DXFLoader.cpp | 14 ++++------ code/Importer.cpp | 23 ++++++++-------- code/SceneCombiner.cpp | 4 +-- code/UnrealLoader.cpp | 10 +++---- include/assimp/BlobIOSystem.h | 2 +- 24 files changed, 168 insertions(+), 177 deletions(-) diff --git a/code/3DSConverter.cpp b/code/3DSConverter.cpp index 081da1bcf..e07ca4c2d 100644 --- a/code/3DSConverter.cpp +++ b/code/3DSConverter.cpp @@ -120,7 +120,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() else if ( (*a) >= mScene->mMaterials.size()) { (*a) = idx; - DefaultLogger::get()->warn("Material index overflow in 3DS file. Using default material"); + ASSIMP_LOG_WARN("Material index overflow in 3DS file. Using default material"); ++cnt; } } @@ -132,7 +132,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() sMat.mDiffuse = aiColor3D(0.3f,0.3f,0.3f); mScene->mMaterials.push_back(sMat); - DefaultLogger::get()->info("3DS: Generating default material"); + ASSIMP_LOG_INFO("3DS: Generating default material"); } } @@ -147,12 +147,12 @@ void Discreet3DSImporter::CheckIndices(D3DS::Mesh& sMesh) { if ((*i).mIndices[a] >= sMesh.mPositions.size()) { - DefaultLogger::get()->warn("3DS: Vertex index overflow)"); + ASSIMP_LOG_WARN("3DS: Vertex index overflow)"); (*i).mIndices[a] = (uint32_t)sMesh.mPositions.size()-1; } if ( !sMesh.mTexCoords.empty() && (*i).mIndices[a] >= sMesh.mTexCoords.size()) { - DefaultLogger::get()->warn("3DS: Texture coordinate index overflow)"); + ASSIMP_LOG_WARN("3DS: Texture coordinate index overflow)"); (*i).mIndices[a] = (uint32_t)sMesh.mTexCoords.size()-1; } } @@ -497,7 +497,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut, pvCurrent->x *= -1.f; t2->x *= -1.f; } - DefaultLogger::get()->info("3DS: Flipping mesh X-Axis"); + ASSIMP_LOG_INFO("3DS: Flipping mesh X-Axis"); } // Handle pivot point @@ -573,11 +573,11 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut, pcIn->aTargetPositionKeys.size() > 1) { aiAnimation* anim = pcSOut->mAnimations[0]; - ai_assert(NULL != anim); + ai_assert(nullptr != anim); if (pcIn->aCameraRollKeys.size() > 1) { - DefaultLogger::get()->debug("3DS: Converting camera roll track ..."); + ASSIMP_LOG_DEBUG("3DS: Converting camera roll track ..."); // Camera roll keys - in fact they're just rotations // around the camera's z axis. The angles are given @@ -597,7 +597,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut, #if 0 if (pcIn->aTargetPositionKeys.size() > 1) { - DefaultLogger::get()->debug("3DS: Converting target track ..."); + ASSIMP_LOG_DEBUG("3DS: Converting target track ..."); // Camera or spot light - need to convert the separate // target position channel to our representation @@ -743,7 +743,7 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut) // | | | | | // MESH_0 MESH_1 MESH_2 ... MESH_N CAMERA_0 .... // - DefaultLogger::get()->warn("No hierarchy information has been found in the file. "); + ASSIMP_LOG_WARN("No hierarchy information has been found in the file. "); pcOut->mRootNode->mNumChildren = pcOut->mNumMeshes + static_cast(mScene->mCameras.size() + mScene->mLights.size()); diff --git a/code/3DSExporter.cpp b/code/3DSExporter.cpp index fcd24d8aa..53976b16f 100644 --- a/code/3DSExporter.cpp +++ b/code/3DSExporter.cpp @@ -381,7 +381,7 @@ void Discreet3DSExporter::WriteTexture(const aiMaterial& mat, aiTextureType type // TODO: handle embedded textures properly if (path.data[0] == '*') { - DefaultLogger::get()->error("Ignoring embedded texture for export: " + std::string(path.C_Str())); + ASSIMP_LOG_ERROR("Ignoring embedded texture for export: " + std::string(path.C_Str())); return; } diff --git a/code/3DSLoader.cpp b/code/3DSLoader.cpp index bfe2bf6e5..3c95d8193 100644 --- a/code/3DSLoader.cpp +++ b/code/3DSLoader.cpp @@ -258,8 +258,9 @@ void Discreet3DSImporter::ReadChunk(Discreet3DS::Chunk* pcOut) if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSize()) throw DeadlyImportError("Chunk is too large"); - if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSizeToLimit()) - DefaultLogger::get()->error("3DS: Chunk overflow"); + if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSizeToLimit()) { + ASSIMP_LOG_ERROR("3DS: Chunk overflow"); + } } // ------------------------------------------------------------------------------------------------ @@ -320,7 +321,7 @@ void Discreet3DSImporter::ParseEditorChunk() // print the version number char buff[10]; ASSIMP_itoa10(buff,stream->GetI2()); - DefaultLogger::get()->info(std::string("3DS file format version: ") + buff); + ASSIMP_LOG_INFO_F(std::string("3DS file format version: "), buff); } break; }; @@ -361,7 +362,7 @@ void Discreet3DSImporter::ParseObjectChunk() if (is_qnan(mClrAmbient.r)) { // We failed to read the ambient base color. - DefaultLogger::get()->error("3DS: Failed to read ambient base color"); + ASSIMP_LOG_ERROR("3DS: Failed to read ambient base color"); mClrAmbient.r = mClrAmbient.g = mClrAmbient.b = 0.0f; } break; @@ -463,7 +464,7 @@ void Discreet3DSImporter::ParseChunk(const char* name, unsigned int num) if (len < 1e-5) { // There are some files with lookat == position. Don't know why or whether it's ok or not. - DefaultLogger::get()->error("3DS: Unable to read proper camera look-at vector"); + ASSIMP_LOG_ERROR("3DS: Unable to read proper camera look-at vector"); camera->mLookAt = aiVector3D(0.0,1.0,0.0); } @@ -629,9 +630,9 @@ void Discreet3DSImporter::SkipTCBInfo() if (!flags) { // Currently we can't do anything with these values. They occur // quite rare, so it wouldn't be worth the effort implementing - // them. 3DS ist not really suitable for complex animations, + // them. 3DS is not really suitable for complex animations, // so full support is not required. - DefaultLogger::get()->warn("3DS: Skipping TCB animation info"); + ASSIMP_LOG_WARN("3DS: Skipping TCB animation info"); } if (flags & Discreet3DS::KEY_USE_TENS) { @@ -732,7 +733,6 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) // If object name is DUMMY, take this one instead if (mCurrentNode->mName == "$$$DUMMY") { - //DefaultLogger::get()->warn("3DS: Skipping dummy object name for non-dummy object"); mCurrentNode->mName = std::string(sz); break; } @@ -743,7 +743,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) if ( Discreet3DS::CHUNK_TRACKINFO != parent) { - DefaultLogger::get()->warn("3DS: Skipping pivot subchunk for non usual object"); + ASSIMP_LOG_WARN("3DS: Skipping pivot subchunk for non usual object"); break; } @@ -805,7 +805,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) { // roll keys are accepted for cameras only if (parent != Discreet3DS::CHUNK_TRACKCAMERA) { - DefaultLogger::get()->warn("3DS: Ignoring roll track for non-camera object"); + ASSIMP_LOG_WARN("3DS: Ignoring roll track for non-camera object"); break; } bool sortKeys = false; @@ -845,7 +845,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) // CAMERA FOV KEYFRAME case Discreet3DS::CHUNK_TRACKFOV: { - DefaultLogger::get()->error("3DS: Skipping FOV animation track. " + ASSIMP_LOG_ERROR("3DS: Skipping FOV animation track. " "This is not supported"); } break; @@ -985,7 +985,7 @@ void Discreet3DSImporter::ParseFaceChunk() } } if (0xcdcdcdcd == idx) { - DefaultLogger::get()->error(std::string("3DS: Unknown material: ") + sz); + ASSIMP_LOG_ERROR_F( "3DS: Unknown material: ", sz); } // Now continue and read all material indices @@ -995,7 +995,7 @@ void Discreet3DSImporter::ParseFaceChunk() // check range if (fidx >= mMesh.mFaceMaterials.size()) { - DefaultLogger::get()->error("3DS: Invalid face index in face material list"); + ASSIMP_LOG_ERROR("3DS: Invalid face index in face material list"); } else mMesh.mFaceMaterials[fidx] = idx; }} @@ -1110,7 +1110,7 @@ void Discreet3DSImporter::ParseMaterialChunk() if (!cnt) { // This may not be, we use the default name instead - DefaultLogger::get()->error("3DS: Empty material name"); + ASSIMP_LOG_ERROR("3DS: Empty material name"); } else mScene->mMaterials.back().mName = std::string(sz,cnt); } @@ -1123,7 +1123,7 @@ void Discreet3DSImporter::ParseMaterialChunk() ParseColorChunk(pc); if (is_qnan(pc->r)) { // color chunk is invalid. Simply ignore it - DefaultLogger::get()->error("3DS: Unable to read DIFFUSE chunk"); + ASSIMP_LOG_ERROR("3DS: Unable to read DIFFUSE chunk"); pc->r = pc->g = pc->b = 1.0f; }} break; @@ -1135,7 +1135,7 @@ void Discreet3DSImporter::ParseMaterialChunk() ParseColorChunk(pc); if (is_qnan(pc->r)) { // color chunk is invalid. Simply ignore it - DefaultLogger::get()->error("3DS: Unable to read SPECULAR chunk"); + ASSIMP_LOG_ERROR("3DS: Unable to read SPECULAR chunk"); pc->r = pc->g = pc->b = 1.0f; }} break; @@ -1147,7 +1147,7 @@ void Discreet3DSImporter::ParseMaterialChunk() ParseColorChunk(pc); if (is_qnan(pc->r)) { // color chunk is invalid. Simply ignore it - DefaultLogger::get()->error("3DS: Unable to read AMBIENT chunk"); + ASSIMP_LOG_ERROR("3DS: Unable to read AMBIENT chunk"); pc->r = pc->g = pc->b = 0.0f; }} break; @@ -1159,7 +1159,7 @@ void Discreet3DSImporter::ParseMaterialChunk() ParseColorChunk(pc); if (is_qnan(pc->r)) { // color chunk is invalid. Simply ignore it - DefaultLogger::get()->error("3DS: Unable to read EMISSIVE chunk"); + ASSIMP_LOG_ERROR("3DS: Unable to read EMISSIVE chunk"); pc->r = pc->g = pc->b = 0.0f; }} break; @@ -1293,7 +1293,7 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut) pcOut->mScaleU = stream->GetF4(); if (0.0f == pcOut->mScaleU) { - DefaultLogger::get()->warn("Texture coordinate scaling in the x direction is zero. Assuming 1."); + ASSIMP_LOG_WARN("Texture coordinate scaling in the x direction is zero. Assuming 1."); pcOut->mScaleU = 1.0f; } break; @@ -1302,7 +1302,7 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut) pcOut->mScaleV = stream->GetF4(); if (0.0f == pcOut->mScaleV) { - DefaultLogger::get()->warn("Texture coordinate scaling in the y direction is zero. Assuming 1."); + ASSIMP_LOG_WARN("Texture coordinate scaling in the y direction is zero. Assuming 1."); pcOut->mScaleV = 1.0f; } break; diff --git a/code/ACLoader.cpp b/code/ACLoader.cpp index 3f8653d5d..7b8afbe9b 100644 --- a/code/ACLoader.cpp +++ b/code/ACLoader.cpp @@ -85,7 +85,7 @@ static const aiImporterDesc desc = { #define AI_AC_SKIP_TO_NEXT_TOKEN() \ if (!SkipSpaces(&buffer)) \ { \ - DefaultLogger::get()->error("AC3D: Unexpected EOF/EOL"); \ + ASSIMP_LOG_ERROR("AC3D: Unexpected EOF/EOL"); \ continue; \ } @@ -101,7 +101,7 @@ static const aiImporterDesc desc = { { \ if (IsLineEnd( *buffer )) \ { \ - DefaultLogger::get()->error("AC3D: Unexpected EOF/EOL in string"); \ + ASSIMP_LOG_ERROR("AC3D: Unexpected EOF/EOL in string"); \ out = "ERROR"; \ break; \ } \ @@ -120,7 +120,7 @@ static const aiImporterDesc desc = { { \ if (strncmp(buffer,name,name_length) || !IsSpace(buffer[name_length])) \ { \ - DefaultLogger::get()->error("AC3D: Unexpexted token. " name " was expected."); \ + ASSIMP_LOG_ERROR("AC3D: Unexpexted token. " name " was expected."); \ continue; \ } \ buffer += name_length+1; \ @@ -217,7 +217,7 @@ void AC3DImporter::LoadObjectSection(std::vector& objects) light->mName.length = ::ai_snprintf(light->mName.data, MAXLEN, "ACLight_%i",static_cast(mLights->size())-1); obj.name = std::string( light->mName.data ); - DefaultLogger::get()->debug("AC3D: Light source encountered"); + ASSIMP_LOG_DEBUG("AC3D: Light source encountered"); obj.type = Object::Light; } else if (!ASSIMP_strincmp(buffer,"group",5)) @@ -307,12 +307,12 @@ void AC3DImporter::LoadObjectSection(std::vector& objects) { if (!GetNextLine()) { - DefaultLogger::get()->error("AC3D: Unexpected EOF: not all vertices have been parsed yet"); + ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: not all vertices have been parsed yet"); break; } else if (!IsNumeric(*buffer)) { - DefaultLogger::get()->error("AC3D: Unexpected token: not all vertices have been parsed yet"); + ASSIMP_LOG_ERROR("AC3D: Unexpected token: not all vertices have been parsed yet"); --buffer; // make sure the line is processed a second time break; } @@ -338,8 +338,8 @@ void AC3DImporter::LoadObjectSection(std::vector& objects) // example writes no surf chunks if (!Q3DWorkAround) { - DefaultLogger::get()->warn("AC3D: SURF token was expected"); - DefaultLogger::get()->debug("Continuing with Quick3D Workaround enabled"); + ASSIMP_LOG_WARN("AC3D: SURF token was expected"); + ASSIMP_LOG_DEBUG("Continuing with Quick3D Workaround enabled"); } --buffer; // make sure the line is processed a second time // break; --- see fix notes above @@ -384,7 +384,7 @@ void AC3DImporter::LoadObjectSection(std::vector& objects) { if(!GetNextLine()) { - DefaultLogger::get()->error("AC3D: Unexpected EOF: surface references are incomplete"); + ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: surface references are incomplete"); break; } surf.entries.push_back(Surface::SurfaceEntry()); @@ -405,7 +405,7 @@ void AC3DImporter::LoadObjectSection(std::vector& objects) } } } - DefaultLogger::get()->error("AC3D: Unexpected EOF: \'kids\' line was expected"); + ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: \'kids\' line was expected"); } // ------------------------------------------------------------------------------------------------ @@ -478,7 +478,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object, therefore: if no surfaces are defined return point data only */ - DefaultLogger::get()->info("AC3D: No surfaces defined in object definition, " + ASSIMP_LOG_INFO("AC3D: No surfaces defined in object definition, " "a point list is returned"); meshes.push_back(new aiMesh()); @@ -519,12 +519,12 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object, unsigned int idx = (*it).mat; if (idx >= needMat.size()) { - DefaultLogger::get()->error("AC3D: material index is out of range"); + ASSIMP_LOG_ERROR("AC3D: material index is out of range"); idx = 0; } if ((*it).entries.empty()) { - DefaultLogger::get()->warn("AC3D: surface her zero vertex references"); + ASSIMP_LOG_WARN("AC3D: surface her zero vertex references"); } // validate all vertex indices to make sure we won't crash here @@ -533,7 +533,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object, { if ((*it2).first >= object.vertices.size()) { - DefaultLogger::get()->warn("AC3D: Invalid vertex reference"); + ASSIMP_LOG_WARN("AC3D: Invalid vertex reference"); (*it2).first = 0; } } @@ -561,7 +561,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object, if ((*it).flags & 0xf) { - DefaultLogger::get()->warn("AC3D: The type flag of a surface is unknown"); + ASSIMP_LOG_WARN("AC3D: The type flag of a surface is unknown"); (*it).flags &= ~(0xf); } @@ -712,7 +712,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object, if (object.subDiv) { if (configEvalSubdivision) { std::unique_ptr div(Subdivider::Create(Subdivider::CATMULL_CLARKE)); - DefaultLogger::get()->info("AC3D: Evaluating subdivision surface: "+object.name); + ASSIMP_LOG_INFO("AC3D: Evaluating subdivision surface: "+object.name); std::vector cpy(meshes.size()-oldm,NULL); div->Subdivide(&meshes[oldm],cpy.size(),&cpy.front(),object.subDiv,true); @@ -721,7 +721,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object, // previous meshes are deleted vy Subdivide(). } else { - DefaultLogger::get()->info("AC3D: Letting the subdivision surface untouched due to my configuration: " + ASSIMP_LOG_INFO("AC3D: Letting the subdivision surface untouched due to my configuration: " +object.name); } } @@ -813,7 +813,7 @@ void AC3DImporter::InternReadFile( const std::string& pFile, unsigned int version = HexDigitToDecimal( buffer[4] ); char msg[3]; ASSIMP_itoa10(msg,3,version); - DefaultLogger::get()->info(std::string("AC3D file format version: ") + msg); + ASSIMP_LOG_INFO_F("AC3D file format version: ", msg); std::vector materials; materials.reserve(5); @@ -857,7 +857,7 @@ void AC3DImporter::InternReadFile( const std::string& pFile, } if (materials.empty()) { - DefaultLogger::get()->warn("AC3D: No material has been found"); + ASSIMP_LOG_WARN("AC3D: No material has been found"); materials.push_back(Material()); } diff --git a/code/ASELoader.cpp b/code/ASELoader.cpp index 32b0eae2d..1808f25e2 100644 --- a/code/ASELoader.cpp +++ b/code/ASELoader.cpp @@ -200,7 +200,7 @@ void ASEImporter::InternReadFile( const std::string& pFile, ConvertMeshes(*i,avOutMeshes); } if (tookNormals) { - DefaultLogger::get()->debug("ASE: Taking normals from the file. Use " + ASSIMP_LOG_DEBUG("ASE: Taking normals from the file. Use " "the AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS setting if you " "experience problems"); } @@ -297,15 +297,15 @@ void ASEImporter::BuildAnimations(const std::vector& nodes) // TODO: Implement Bezier & TCB support if ((*i)->mAnim.mPositionType != ASE::Animation::TRACK) { - DefaultLogger::get()->warn("ASE: Position controller uses Bezier/TCB keys. " + ASSIMP_LOG_WARN("ASE: Position controller uses Bezier/TCB keys. " "This is not supported."); } if ((*i)->mAnim.mRotationType != ASE::Animation::TRACK) { - DefaultLogger::get()->warn("ASE: Rotation controller uses Bezier/TCB keys. " + ASSIMP_LOG_WARN("ASE: Rotation controller uses Bezier/TCB keys. " "This is not supported."); } if ((*i)->mAnim.mScalingType != ASE::Animation::TRACK) { - DefaultLogger::get()->warn("ASE: Position controller uses Bezier/TCB keys. " + ASSIMP_LOG_WARN("ASE: Position controller uses Bezier/TCB keys. " "This is not supported."); } @@ -624,7 +624,7 @@ void ASEImporter::AddNodes (const std::vector& nodes, node->mNumChildren++; // What we did is so great, it is at least worth a debug message - DefaultLogger::get()->debug("ASE: Generating separate target node ("+snode->mName+")"); + ASSIMP_LOG_DEBUG("ASE: Generating separate target node ("+snode->mName+")"); } } @@ -947,7 +947,7 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector& avOutMesh // validate the material index of the mesh if (mesh.iMaterialIndex >= mParser->m_vMaterials.size()) { mesh.iMaterialIndex = (unsigned int)mParser->m_vMaterials.size()-1; - DefaultLogger::get()->warn("Material index is out of range"); + ASSIMP_LOG_WARN("Material index is out of range"); } // If the material the mesh is assigned to is consisting of submeshes, split it @@ -957,11 +957,11 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector& avOutMesh std::vector* aiSplit = new std::vector[vSubMaterials.size()]; - // build a list of all faces per submaterial + // build a list of all faces per sub-material for (unsigned int i = 0; i < mesh.mFaces.size();++i) { // check range if (mesh.mFaces[i].iMaterial >= vSubMaterials.size()) { - DefaultLogger::get()->warn("Submaterial index is out of range"); + ASSIMP_LOG_WARN("Submaterial index is out of range"); // use the last material instead aiSplit[vSubMaterials.size()-1].push_back(i); diff --git a/code/ASEParser.cpp b/code/ASEParser.cpp index b953f8d96..298c6fe61 100644 --- a/code/ASEParser.cpp +++ b/code/ASEParser.cpp @@ -151,7 +151,7 @@ void Parser::LogWarning(const char* szWarn) #endif // output the warning to the logger ... - DefaultLogger::get()->warn(szTemp); + ASSIMP_LOG_WARN(szTemp); } // ------------------------------------------------------------------------------------------------ @@ -167,7 +167,7 @@ void Parser::LogInfo(const char* szWarn) #endif // output the information to the logger ... - DefaultLogger::get()->info(szTemp); + ASSIMP_LOG_INFO(szTemp); } // ------------------------------------------------------------------------------------------------ @@ -758,7 +758,7 @@ void Parser::ParseLV3MapBlock(Texture& map) SkipToNextToken(); if (temp != "Bitmap" && temp != "Normal Bump") { - DefaultLogger::get()->warn("ASE: Skipping unknown map type: " + temp); + ASSIMP_LOG_WARN_F("ASE: Skipping unknown map type: ", temp); parsePath = false; } continue; @@ -773,7 +773,7 @@ void Parser::ParseLV3MapBlock(Texture& map) { // Files with 'None' as map name are produced by // an Maja to ASE exporter which name I forgot .. - DefaultLogger::get()->warn("ASE: Skipping invalid map entry"); + ASSIMP_LOG_WARN("ASE: Skipping invalid map entry"); map.mMapName = ""; } @@ -1072,7 +1072,7 @@ void Parser::ParseLV2AnimationBlock(ASE::BaseNode& mesh) ( mesh.mType != BaseNode::Light || ((ASE::Light&)mesh).mLightType != ASE::Light::TARGET)) { - DefaultLogger::get()->error("ASE: Found target animation channel " + ASSIMP_LOG_ERROR("ASE: Found target animation channel " "but the node is neither a camera nor a spot light"); anim = NULL; } @@ -1098,7 +1098,7 @@ void Parser::ParseLV2AnimationBlock(ASE::BaseNode& mesh) if (!anim || anim == &mesh.mTargetAnim) { // Target animation channels may have no rotation channels - DefaultLogger::get()->error("ASE: Ignoring scaling channel in target animation"); + ASSIMP_LOG_ERROR("ASE: Ignoring scaling channel in target animation"); SkipSection(); } else ParseLV3ScaleAnimationBlock(*anim); @@ -1112,7 +1112,7 @@ void Parser::ParseLV2AnimationBlock(ASE::BaseNode& mesh) if (!anim || anim == &mesh.mTargetAnim) { // Target animation channels may have no rotation channels - DefaultLogger::get()->error("ASE: Ignoring rotation channel in target animation"); + ASSIMP_LOG_ERROR("ASE: Ignoring rotation channel in target animation"); SkipSection(); } else ParseLV3RotAnimationBlock(*anim); @@ -1295,12 +1295,14 @@ void Parser::ParseLV2NodeTransformBlock(ASE::BaseNode& mesh) { mode = 2; } - else DefaultLogger::get()->error("ASE: Ignoring target transform, " - "this is no spot light or target camera"); + else { + ASSIMP_LOG_ERROR("ASE: Ignoring target transform, " + "this is no spot light or target camera"); + } } else { - DefaultLogger::get()->error("ASE: Unknown node transformation: " + temp); + ASSIMP_LOG_ERROR("ASE: Unknown node transformation: " + temp); // mode = 0 } continue; @@ -1916,7 +1918,7 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh) else if (index == face.mIndices[2]) index = 2; else { - DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_VERTEXNORMAL section"); + ASSIMP_LOG_ERROR("ASE: Invalid vertex index in MESH_VERTEXNORMAL section"); continue; } // We'll renormalize later @@ -1928,7 +1930,7 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh) ParseLV4MeshFloatTriple(&vNormal.x,faceIdx); if (faceIdx >= sMesh.mFaces.size()) { - DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_FACENORMAL section"); + ASSIMP_LOG_ERROR("ASE: Invalid vertex index in MESH_FACENORMAL section"); continue; } diff --git a/code/B3DImporter.cpp b/code/B3DImporter.cpp index e4572f8eb..ce8bd5159 100644 --- a/code/B3DImporter.cpp +++ b/code/B3DImporter.cpp @@ -614,7 +614,7 @@ void B3DImporter::ReadBB3D( aiScene *scene ){ if (!DefaultLogger::isNullLogger()) { char dmp[128]; ai_snprintf(dmp, 128, "B3D file format version: %i",version); - DefaultLogger::get()->info(dmp); + ASSIMP_LOG_INFO(dmp); } while( ChunkSize() ){ diff --git a/code/BaseImporter.cpp b/code/BaseImporter.cpp index 4782e9e2d..fa9f70603 100644 --- a/code/BaseImporter.cpp +++ b/code/BaseImporter.cpp @@ -64,23 +64,24 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer BaseImporter::BaseImporter() -: m_progress() -{ +: m_progress() { // nothing to do here } // ------------------------------------------------------------------------------------------------ // Destructor, private as well -BaseImporter::~BaseImporter() -{ +BaseImporter::~BaseImporter() { // nothing to do here } // ------------------------------------------------------------------------------------------------ // Imports the given file and returns the imported data. -aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile, IOSystem* pIOHandler) -{ +aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile, IOSystem* pIOHandler) { m_progress = pImp->GetProgressHandler(); + if (nullptr == m_progress) { + return nullptr; + } + ai_assert(m_progress); // Gather configuration properties for this run @@ -100,8 +101,8 @@ aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile, } catch( const std::exception& err ) { // extract error description m_ErrorText = err.what(); - DefaultLogger::get()->error(m_ErrorText); - return NULL; + ASSIMP_LOG_ERROR(m_ErrorText); + return nullptr; } // return what we gathered from the import. @@ -195,7 +196,7 @@ void BaseImporter::GetExtensionList(std::set& extensions) { // We got a match, either we don't care where it is, or it happens to // be in the beginning of the file / line if (!tokensSol || r == buffer || r[-1] == '\r' || r[-1] == '\n') { - DefaultLogger::get()->debug(std::string("Found positive match for header keyword: ") + tokens[i]); + ASSIMP_LOG_DEBUG_F( "Found positive match for header keyword: ", tokens[i] ); return true; } } @@ -322,7 +323,7 @@ void BaseImporter::ConvertToUTF8(std::vector& data) // UTF 8 with BOM if((uint8_t)data[0] == 0xEF && (uint8_t)data[1] == 0xBB && (uint8_t)data[2] == 0xBF) { - DefaultLogger::get()->debug("Found UTF-8 BOM ..."); + ASSIMP_LOG_DEBUG("Found UTF-8 BOM ..."); std::copy(data.begin()+3,data.end(),data.begin()); data.resize(data.size()-3); @@ -341,7 +342,7 @@ void BaseImporter::ConvertToUTF8(std::vector& data) // UTF 32 LE with BOM if(*((uint32_t*)&data.front()) == 0x0000FFFE) { - DefaultLogger::get()->debug("Found UTF-32 BOM ..."); + ASSIMP_LOG_DEBUG("Found UTF-32 BOM ..."); std::vector output; int *ptr = (int*)&data[ 0 ]; @@ -361,7 +362,7 @@ void BaseImporter::ConvertToUTF8(std::vector& data) // UTF 16 LE with BOM if(*((uint16_t*)&data.front()) == 0xFEFF) { - DefaultLogger::get()->debug("Found UTF-16 BOM ..."); + ASSIMP_LOG_DEBUG("Found UTF-16 BOM ..."); std::vector output; utf8::utf16to8(data.begin(), data.end(), back_inserter(output)); @@ -386,16 +387,14 @@ void BaseImporter::ConvertUTF8toISO8859_1(std::string& data) data[j] = ((unsigned char) data[++i] + 0x40); } else { std::stringstream stream; - stream << "UTF8 code " << std::hex << data[i] << data[i + 1] << " can not be converted into ISA-8859-1."; - - DefaultLogger::get()->error(stream.str()); + ASSIMP_LOG_ERROR( stream.str() ); data[j++] = data[i++]; data[j] = data[i]; } } else { - DefaultLogger::get()->error("UTF8 code but only one character remaining"); + ASSIMP_LOG_ERROR("UTF8 code but only one character remaining"); data[j] = data[i]; } @@ -411,7 +410,7 @@ void BaseImporter::TextFileToBuffer(IOStream* stream, std::vector& data, TextFileMode mode) { - ai_assert(NULL != stream); + ai_assert(nullptr != stream); const size_t fileSize = stream->FileSize(); if (mode == FORBID_EMPTY) { @@ -472,14 +471,14 @@ struct Assimp::BatchData { , pImporter( nullptr ) , next_id(0xffff) , validate( validate ) { - ai_assert( NULL != pIO ); + ai_assert( nullptr != pIO ); pImporter = new Importer(); pImporter->SetIOHandler( pIO ); } ~BatchData() { - pImporter->SetIOHandler( NULL ); /* get pointer back into our possession */ + pImporter->SetIOHandler( nullptr ); /* get pointer back into our possession */ delete pImporter; } @@ -505,9 +504,8 @@ struct Assimp::BatchData { typedef std::list::iterator LoadReqIt; // ------------------------------------------------------------------------------------------------ -BatchLoader::BatchLoader(IOSystem* pIO, bool validate ) -{ - ai_assert(NULL != pIO); +BatchLoader::BatchLoader(IOSystem* pIO, bool validate ) { + ai_assert(nullptr != pIO); m_data = new BatchData( pIO, validate ); } @@ -573,7 +571,7 @@ aiScene* BatchLoader::GetImport( unsigned int which ) return sc; } } - return NULL; + return nullptr; } // ------------------------------------------------------------------------------------------------ @@ -596,13 +594,13 @@ void BatchLoader::LoadAll() if (!DefaultLogger::isNullLogger()) { - DefaultLogger::get()->info("%%% BEGIN EXTERNAL FILE %%%"); - DefaultLogger::get()->info("File: " + (*it).file); + ASSIMP_LOG_INFO("%%% BEGIN EXTERNAL FILE %%%"); + ASSIMP_LOG_INFO("File: ", (*it).file); } m_data->pImporter->ReadFile((*it).file,pp); (*it).scene = m_data->pImporter->GetOrphanedScene(); (*it).loaded = true; - DefaultLogger::get()->info("%%% END EXTERNAL FILE %%%"); + ASSIMP_LOG_INFO("%%% END EXTERNAL FILE %%%"); } } diff --git a/code/BaseProcess.cpp b/code/BaseProcess.cpp index 8508f59e4..ba968a819 100644 --- a/code/BaseProcess.cpp +++ b/code/BaseProcess.cpp @@ -85,7 +85,7 @@ void BaseProcess::ExecuteOnScene( Importer* pImp) // extract error description pImp->Pimpl()->mErrorString = err.what(); - DefaultLogger::get()->error(pImp->Pimpl()->mErrorString); + ASSIMP_LOG_ERROR(pImp->Pimpl()->mErrorString); // and kill the partially imported data delete pImp->Pimpl()->mScene; diff --git a/code/BlenderDNA.cpp b/code/BlenderDNA.cpp index 1d88f8fa6..0bca902c6 100644 --- a/code/BlenderDNA.cpp +++ b/code/BlenderDNA.cpp @@ -210,8 +210,7 @@ void DNAParser::Parse () s.size = offset; } - DefaultLogger::get()->debug((format(),"BlenderDNA: Got ",dna.structures.size(), - " structures with totally ",fields," fields")); + ASSIMP_LOG_DEBUG( "BlenderDNA: Got ", dna.structures.size()," structures with totally ",fields," fields"); #ifdef ASSIMP_BUILD_BLENDER_DEBUG dna.DumpToFile(); @@ -233,7 +232,7 @@ void DNA :: DumpToFile() std::ofstream f("dna.txt"); if (f.fail()) { - DefaultLogger::get()->error("Could not dump dna to dna.txt"); + ASSIMP_LOG_ERROR("Could not dump dna to dna.txt"); return; } f << "Field format: type name offset size" << "\n"; @@ -248,7 +247,7 @@ void DNA :: DumpToFile() } f << std::flush; - DefaultLogger::get()->info("BlenderDNA: Dumped dna to dna.txt"); + ASSIMP_LOG_INFO("BlenderDNA: Dumped dna to dna.txt"); } #endif @@ -367,7 +366,7 @@ void SectionParser :: Next() } #ifdef ASSIMP_BUILD_BLENDER_DEBUG - DefaultLogger::get()->debug(current.id); + ASSIMP_LOG_DEBUG(current.id); #endif } diff --git a/code/BlenderDNA.h b/code/BlenderDNA.h index 3a2455275..4a1e83b64 100644 --- a/code/BlenderDNA.h +++ b/code/BlenderDNA.h @@ -381,7 +381,7 @@ template <> struct Structure :: _defaultInitializer { template void operator ()(T& out, const char* reason = "") { - DefaultLogger::get()->warn(reason); + ASSIMP_LOG_WARN(reason); // ... and let the show go on _defaultInitializer<0 /*ErrorPolicy_Igno*/>()(out); diff --git a/code/BlenderDNA.inl b/code/BlenderDNA.inl index 163798a40..1f345b631 100644 --- a/code/BlenderDNA.inl +++ b/code/BlenderDNA.inl @@ -468,9 +468,7 @@ template <> bool Structure :: ResolvePointer(std::shar // this might happen if DNA::RegisterConverters hasn't been called so far // or if the target type is not contained in `our` DNA. out.reset(); - DefaultLogger::get()->warn((Formatter::format(), - "Failed to find a converter for the `",s.name,"` structure" - )); + ASSIMP_LOG_WARN( "Failed to find a converter for the `",s.name,"` structure" ); return false; } diff --git a/code/BlenderLoader.cpp b/code/BlenderLoader.cpp index d4d6473c5..71880e3ac 100644 --- a/code/BlenderLoader.cpp +++ b/code/BlenderLoader.cpp @@ -327,12 +327,12 @@ void BlenderImporter::ExtractScene(Scene& out, const FileDatabase& file) ss.Convert(out,file); #ifndef ASSIMP_BUILD_BLENDER_NO_STATS - DefaultLogger::get()->info((format(), + ASSIMP_LOG_INFO_F( "(Stats) Fields read: " ,file.stats().fields_read, ", pointers resolved: " ,file.stats().pointers_resolved, ", cache hits: " ,file.stats().cache_hits, ", cached objects: " ,file.stats().cached_objects - )); + ); #endif } diff --git a/code/BlenderModifier.h b/code/BlenderModifier.h index cd34659c9..1b0976b1e 100644 --- a/code/BlenderModifier.h +++ b/code/BlenderModifier.h @@ -86,7 +86,7 @@ public: const Scene& /*in*/, const Object& /*orig_object*/ ) { - DefaultLogger::get()->warn((Formatter::format("This modifier is not supported, skipping: "),orig_modifier.dna_type)); + ASSIMP_LOG_INFO_F("This modifier is not supported, skipping: "),orig_modifier.dna_type); return; } }; diff --git a/code/COBLoader.cpp b/code/COBLoader.cpp index 222088cbd..ae65f8f93 100644 --- a/code/COBLoader.cpp +++ b/code/COBLoader.cpp @@ -150,7 +150,7 @@ void COBImporter::InternReadFile( const std::string& pFile, ThrowException("Could not found magic id: `Caligari`"); } - DefaultLogger::get()->info("File format tag: "+std::string(head+9,6)); + ASSIMP_LOG_INFO_F("File format tag: ",std::string(head+9,6)); if (head[16]!='L') { ThrowException("File is big-endian, which is not supported"); } @@ -303,7 +303,7 @@ aiNode* COBImporter::BuildNodes(const Node& root,const Scene& scin,aiScene* fill } std::unique_ptr defmat; if(!min) { - DefaultLogger::get()->debug(format()<<"Could not resolve material index " + ASSIMP_LOG_DEBUG(format()<<"Could not resolve material index " <(-1)) { - DefaultLogger::get()->error(error); + ASSIMP_LOG_ERROR(error); // (HACK) - our current position in the stream is the beginning of the // head line of the next chunk. That's fine, but the caller is going @@ -935,7 +935,7 @@ void COBImporter::UnsupportedChunk_Binary( StreamReaderLE& reader, const ChunkIn // we can recover if the chunk size was specified. if(nfo.size != static_cast(-1)) { - DefaultLogger::get()->error(error); + ASSIMP_LOG_ERROR(error); reader.IncPtr(nfo.size); } else ThrowException(error); diff --git a/code/ColladaLoader.cpp b/code/ColladaLoader.cpp index 4bb5f4521..a26df1898 100644 --- a/code/ColladaLoader.cpp +++ b/code/ColladaLoader.cpp @@ -294,7 +294,7 @@ void ColladaLoader::ResolveNodeInstances( const ColladaParser& pParser, const Co nd = FindNode(pParser.mRootNode, nodeInst.mNode); } if (!nd) - DefaultLogger::get()->error("Collada: Unable to resolve reference to instanced node " + nodeInst.mNode); + ASSIMP_LOG_ERROR_F("Collada: Unable to resolve reference to instanced node ", nodeInst.mNode); else { // attach this node to the list of children @@ -311,7 +311,7 @@ void ColladaLoader::ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler std::map::const_iterator it = table.mMap.find(sampler.mUVChannel); if (it != table.mMap.end()) { if (it->second.mType != Collada::IT_Texcoord) - DefaultLogger::get()->error("Collada: Unexpected effect input mapping"); + ASSIMP_LOG_ERROR("Collada: Unexpected effect input mapping"); sampler.mUVId = it->second.mSet; } @@ -327,7 +327,7 @@ void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Coll ColladaParser::LightLibrary::const_iterator srcLightIt = pParser.mLightLibrary.find( lid.mLight); if( srcLightIt == pParser.mLightLibrary.end()) { - DefaultLogger::get()->warn("Collada: Unable to find light for ID \"" + lid.mLight + "\". Skipping."); + ASSIMP_LOG_WARN_F("Collada: Unable to find light for ID \"" , lid.mLight , "\". Skipping."); continue; } const Collada::Light* srcLight = &srcLightIt->second; @@ -395,14 +395,14 @@ void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Col ColladaParser::CameraLibrary::const_iterator srcCameraIt = pParser.mCameraLibrary.find( cid.mCamera); if( srcCameraIt == pParser.mCameraLibrary.end()) { - DefaultLogger::get()->warn("Collada: Unable to find camera for ID \"" + cid.mCamera + "\". Skipping."); + ASSIMP_LOG_WARN_F("Collada: Unable to find camera for ID \"" , cid.mCamera , "\". Skipping."); continue; } const Collada::Camera* srcCamera = &srcCameraIt->second; // orthographic cameras not yet supported in Assimp if (srcCamera->mOrtho) { - DefaultLogger::get()->warn("Collada: Orthographic cameras are not supported."); + ASSIMP_LOG_WARN("Collada: Orthographic cameras are not supported."); } // now fill our ai data structure @@ -472,7 +472,7 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll if( !srcMesh) { - DefaultLogger::get()->warn( format() << "Collada: Unable to find geometry for ID \"" << mid.mMeshOrController << "\". Skipping." ); + ASSIMP_LOG_WARN( "Collada: Unable to find geometry for ID \"", mid.mMeshOrController, "\". Skipping." ); continue; } } else @@ -501,7 +501,8 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll } else { - DefaultLogger::get()->warn( format() << "Collada: No material specified for subgroup <" << submesh.mMaterial << "> in geometry <" << mid.mMeshOrController << ">." ); + ASSIMP_LOG_WARN_F( "Collada: No material specified for subgroup <", submesh.mMaterial, "> in geometry <", + mid.mMeshOrController, ">." ); if( !mid.mMaterials.empty() ) meshMaterial = mid.mMaterials.begin()->second.mMatName; } @@ -874,7 +875,7 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada:: if( bnode) bone->mName.Set( FindNameForNode( bnode)); else - DefaultLogger::get()->warn( format() << "ColladaLoader::CreateMesh(): could not find corresponding node for joint \"" << bone->mName.data << "\"." ); + ASSIMP_LOG_WARN( "ColladaLoader::CreateMesh(): could not find corresponding node for joint \"", bone->mName.data, "\"." ); // and insert bone dstMesh->mBones[boneCount++] = bone; @@ -1175,7 +1176,7 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars else if( subElement == "Z") entry.mSubElement = 2; else - DefaultLogger::get()->warn( format() << "Unknown anim subelement <" << subElement << ">. Ignoring" ); + ASSIMP_LOG_WARN( "Unknown anim subelement <", subElement, ">. Ignoring" ); } else { // no subelement following, transformId is remaining string @@ -1406,7 +1407,7 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars anims.push_back( dstAnim); } else { - DefaultLogger::get()->warn( "Collada loader: found empty animation channel, ignored. Please check your exporter."); + ASSIMP_LOG_WARN( "Collada loader: found empty animation channel, ignored. Please check your exporter."); } if( !entries.empty() && entries.front().mTimeAccessor->mCount > 0 ) @@ -1561,7 +1562,7 @@ void ColladaLoader::AddTexture ( aiMaterial& mat, const ColladaParser& pParser, } } if (-1 == map) { - DefaultLogger::get()->warn("Collada: unable to determine UV channel for texture"); + ASSIMP_LOG_WARN("Collada: unable to determine UV channel for texture"); map = 0; } } @@ -1598,7 +1599,7 @@ void ColladaLoader::FillMaterials( const ColladaParser& pParser, aiScene* /*pSce break; default: - DefaultLogger::get()->warn("Collada: Unrecognized shading mode, using gouraud shading"); + ASSIMP_LOG_WARN("Collada: Unrecognized shading mode, using gouraud shading"); shadeMode = aiShadingMode_Gouraud; break; } @@ -1752,11 +1753,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find( name); if( imIt == pParser.mImageLibrary.end()) { - //missing texture should not stop the conversion - //throw DeadlyImportError( format() << - // "Collada: Unable to resolve effect texture entry \"" << pName << "\", ended up at ID \"" << name << "\"." ); - - DefaultLogger::get()->warn("Collada: Unable to resolve effect texture entry \"" + pName + "\", ended up at ID \"" + name + "\"."); + ASSIMP_LOG_WARN_F("Collada: Unable to resolve effect texture entry \"", pName, "\", ended up at ID \"", name, "\"."); //set default texture file name result.Set(name + ".jpg"); @@ -1775,7 +1772,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars // setup format hint if (imIt->second.mEmbeddedFormat.length() > 3) { - DefaultLogger::get()->warn("Collada: texture format hint is too long, truncating to 3 characters"); + ASSIMP_LOG_WARN("Collada: texture format hint is too long, truncating to 3 characters"); } strncpy(tex->achFormatHint,imIt->second.mEmbeddedFormat.c_str(),3); diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index 31fbabe0e..20d6a39d5 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -152,22 +152,22 @@ void ColladaParser::ReadContents() if (!::strncmp(version,"1.5",3)) { mFormat = FV_1_5_n; - DefaultLogger::get()->debug("Collada schema version is 1.5.n"); + ASSIMP_LOG_DEBUG("Collada schema version is 1.5.n"); } else if (!::strncmp(version,"1.4",3)) { mFormat = FV_1_4_n; - DefaultLogger::get()->debug("Collada schema version is 1.4.n"); + ASSIMP_LOG_DEBUG("Collada schema version is 1.4.n"); } else if (!::strncmp(version,"1.3",3)) { mFormat = FV_1_3_n; - DefaultLogger::get()->debug("Collada schema version is 1.3.n"); + ASSIMP_LOG_DEBUG("Collada schema version is 1.3.n"); } } ReadStructure(); } else { - DefaultLogger::get()->debug( format() << "Ignoring global element <" << mReader->getNodeName() << ">." ); + ASSIMP_LOG_DEBUG_F( "Ignoring global element <", mReader->getNodeName(), ">." ); SkipElement(); } } else @@ -984,13 +984,13 @@ void ColladaParser::ReadImage( Collada::Image& pImage) // they're not skipped. int attrib = TestAttribute("array_index"); if (attrib != -1 && mReader->getAttributeValueAsInt(attrib) > 0) { - DefaultLogger::get()->warn("Collada: Ignoring texture array index"); + ASSIMP_LOG_WARN("Collada: Ignoring texture array index"); continue; } attrib = TestAttribute("mip_index"); if (attrib != -1 && mReader->getAttributeValueAsInt(attrib) > 0) { - DefaultLogger::get()->warn("Collada: Ignoring MIP map layer"); + ASSIMP_LOG_WARN("Collada: Ignoring MIP map layer"); continue; } @@ -1011,7 +1011,7 @@ void ColladaParser::ReadImage( Collada::Image& pImage) // embedded image. get format const int attrib = TestAttribute("format"); if (-1 == attrib) - DefaultLogger::get()->warn("Collada: Unknown image file format"); + ASSIMP_LOG_WARN("Collada: Unknown image file format"); else pImage.mEmbeddedFormat = mReader->getAttributeValue(attrib); const char* data = GetTextContent(); @@ -1590,7 +1590,7 @@ void ColladaParser::ReadSamplerProperties( Sampler& out ) out.mOp = aiTextureOp_Multiply; else { - DefaultLogger::get()->warn("Collada: Unsupported MAYA texture blend mode"); + ASSIMP_LOG_WARN("Collada: Unsupported MAYA texture blend mode"); } TestClosing( "blend_mode"); } @@ -2541,7 +2541,7 @@ void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, si if( pInput.mIndex == 0) pMesh->mPositions.push_back( aiVector3D( obj[0], obj[1], obj[2])); else - DefaultLogger::get()->error("Collada: just one vertex position stream supported"); + ASSIMP_LOG_ERROR("Collada: just one vertex position stream supported"); break; case IT_Normal: // pad to current vertex count if necessary @@ -2552,7 +2552,7 @@ void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, si if( pInput.mIndex == 0) pMesh->mNormals.push_back( aiVector3D( obj[0], obj[1], obj[2])); else - DefaultLogger::get()->error("Collada: just one vertex normal stream supported"); + ASSIMP_LOG_ERROR("Collada: just one vertex normal stream supported"); break; case IT_Tangent: // pad to current vertex count if necessary @@ -2563,7 +2563,7 @@ void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, si if( pInput.mIndex == 0) pMesh->mTangents.push_back( aiVector3D( obj[0], obj[1], obj[2])); else - DefaultLogger::get()->error("Collada: just one vertex tangent stream supported"); + ASSIMP_LOG_ERROR("Collada: just one vertex tangent stream supported"); break; case IT_Bitangent: // pad to current vertex count if necessary @@ -2574,7 +2574,7 @@ void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, si if( pInput.mIndex == 0) pMesh->mBitangents.push_back( aiVector3D( obj[0], obj[1], obj[2])); else - DefaultLogger::get()->error("Collada: just one vertex bitangent stream supported"); + ASSIMP_LOG_ERROR("Collada: just one vertex bitangent stream supported"); break; case IT_Texcoord: // up to 4 texture coord sets are fine, ignore the others @@ -2590,7 +2590,7 @@ void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, si pMesh->mNumUVComponents[pInput.mIndex]=3; } else { - DefaultLogger::get()->error("Collada: too many texture coordinate sets. Skipping."); + ASSIMP_LOG_ERROR("Collada: too many texture coordinate sets. Skipping."); } break; case IT_Color: @@ -2610,7 +2610,7 @@ void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, si pMesh->mColors[pInput.mIndex].push_back(result); } else { - DefaultLogger::get()->error("Collada: too many vertex color sets. Skipping."); + ASSIMP_LOG_ERROR("Collada: too many vertex color sets. Skipping."); } break; @@ -2739,7 +2739,7 @@ void ColladaParser::ReadSceneNode( Node* pNode) { const char* s = mReader->getAttributeValue(attrId); if (s[0] != '#') - DefaultLogger::get()->error("Collada: Unresolved reference format of camera"); + ASSIMP_LOG_ERROR("Collada: Unresolved reference format of camera"); else pNode->mPrimaryCamera = s+1; } @@ -2752,7 +2752,7 @@ void ColladaParser::ReadSceneNode( Node* pNode) { const char* s = mReader->getAttributeValue(attrID); if (s[0] != '#') - DefaultLogger::get()->error("Collada: Unresolved reference format of node"); + ASSIMP_LOG_ERROR("Collada: Unresolved reference format of node"); else { pNode->mNodeInstances.push_back(NodeInstance()); diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index 2732c73c4..0a3a140f3 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -396,7 +396,7 @@ private: return false; } } - DefaultLogger::get()->error("unexpected EOF, expected closing <" + closeTag + "> tag"); + ASSIMP_LOG_ERROR("unexpected EOF, expected closing <" + closeTag + "> tag"); return false; } diff --git a/code/D3MFOpcPackage.cpp b/code/D3MFOpcPackage.cpp index 3bf545813..8161a31e4 100644 --- a/code/D3MFOpcPackage.cpp +++ b/code/D3MFOpcPackage.cpp @@ -465,7 +465,7 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile) } } - DefaultLogger::get()->debug(rootFile); + ASSIMP_LOG_DEBUG(rootFile); mRootStream = mZipArchive->Open(rootFile.c_str()); ai_assert( mRootStream != nullptr ); diff --git a/code/DXFLoader.cpp b/code/DXFLoader.cpp index c8aee18dd..6c42d0fc2 100644 --- a/code/DXFLoader.cpp +++ b/code/DXFLoader.cpp @@ -212,7 +212,7 @@ void DXFImporter::InternReadFile( const std::string& pFile, ++reader; } if (!eof) { - DefaultLogger::get()->warn("DXF: EOF reached, but did not encounter DXF EOF marker"); + ASSIMP_LOG_WARN("DXF: EOF reached, but did not encounter DXF EOF marker"); } ConvertMeshes(pScene,output); @@ -229,7 +229,7 @@ void DXFImporter::InternReadFile( const std::string& pFile, void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output) { // the process of resolving all the INSERT statements can grow the - // polycount excessively, so log the original number. + // poly-count excessively, so log the original number. // XXX Option to import blocks as separate nodes? if (!DefaultLogger::isNullLogger()) { @@ -241,16 +241,14 @@ void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output) } } - DefaultLogger::get()->debug((Formatter::format("DXF: Unexpanded polycount is "), - icount,", vertex count is ",vcount - )); + ASSIMP_LOG_DEBUG("DXF: Unexpanded polycount is ", icount, ", vertex count is ", vcount); } if (! output.blocks.size() ) { throw DeadlyImportError("DXF: no data blocks loaded"); } - DXF::Block* entities = 0; + DXF::Block* entities( nullptr ); // index blocks by name DXF::BlockMap blocks_by_name; @@ -375,9 +373,7 @@ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& bloc // first check if the referenced blocks exists ... const DXF::BlockMap::const_iterator it = blocks_by_name.find(insert.name); if (it == blocks_by_name.end()) { - DefaultLogger::get()->error((Formatter::format("DXF: Failed to resolve block reference: "), - insert.name,"; skipping" - )); + ASSIMP_LOG_ERROR("DXF: Failed to resolve block reference: ", insert.name,"; skipping" ); continue; } diff --git a/code/Importer.cpp b/code/Importer.cpp index 6f9b47562..1b3ccf2a1 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -368,11 +368,11 @@ bool Importer::IsDefaultProgressHandler() const bool _ValidateFlags(unsigned int pFlags) { if (pFlags & aiProcess_GenSmoothNormals && pFlags & aiProcess_GenNormals) { - DefaultLogger::get()->error("#aiProcess_GenSmoothNormals and #aiProcess_GenNormals are incompatible"); + ASSIMP_LOG_ERROR("#aiProcess_GenSmoothNormals and #aiProcess_GenNormals are incompatible"); return false; } if (pFlags & aiProcess_OptimizeGraph && pFlags & aiProcess_PreTransformVertices) { - DefaultLogger::get()->error("#aiProcess_OptimizeGraph and #aiProcess_PreTransformVertices are incompatible"); + ASSIMP_LOG_ERROR("#aiProcess_OptimizeGraph and #aiProcess_PreTransformVertices are incompatible"); return false; } return true; @@ -594,7 +594,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) if( !pimpl->mIOHandler->Exists( pFile)) { pimpl->mErrorString = "Unable to open file \"" + pFile + "\"."; - DefaultLogger::get()->error(pimpl->mErrorString); + ASSIMP_LOG_ERROR(pimpl->mErrorString); return NULL; } @@ -628,7 +628,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) // Put a proper error message if no suitable importer was found if( !imp) { pimpl->mErrorString = "No suitable reader found for the file format of file \"" + pFile + "\"."; - DefaultLogger::get()->error(pimpl->mErrorString); + ASSIMP_LOG_ERROR(pimpl->mErrorString); return NULL; } } @@ -716,7 +716,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) pimpl->mErrorString = std::string("std::exception: ") + e.what(); #endif - DefaultLogger::get()->error(pimpl->mErrorString); + ASSIMP_LOG_ERROR(pimpl->mErrorString); delete pimpl->mScene; pimpl->mScene = NULL; } #endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS @@ -762,7 +762,7 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) if (pimpl->bExtraVerbose) { #ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS - DefaultLogger::get()->error("Verbose Import is not available due to build settings"); + ASSIMP_LOG_ERROR("Verbose Import is not available due to build settings"); #endif // no validation pFlags |= aiProcess_ValidateDataStructure; } @@ -800,18 +800,19 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) // If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step if (pimpl->bExtraVerbose) { - DefaultLogger::get()->debug("Verbose Import: revalidating data structures"); + DefaultLogger::get()->debug("Verbose Import: re-validating data structures"); ValidateDSProcess ds; ds.ExecuteOnScene (this); if( !pimpl->mScene) { - DefaultLogger::get()->error("Verbose Import: failed to revalidate data structures"); + ASSIMP_LOG_ERROR("Verbose Import: failed to re-validate data structures"); break; } } #endif // ! DEBUG } - pimpl->mProgressHandler->UpdatePostProcess( static_cast(pimpl->mPostProcessingSteps.size()), static_cast(pimpl->mPostProcessingSteps.size()) ); + pimpl->mProgressHandler->UpdatePostProcess( static_cast(pimpl->mPostProcessingSteps.size()), + static_cast(pimpl->mPostProcessingSteps.size()) ); // update private scene flags if( pimpl->mScene ) @@ -858,7 +859,7 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess if ( pimpl->bExtraVerbose ) { #ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS - DefaultLogger::get()->error( "Verbose Import is not available due to build settings" ); + ASSIMP_LOG_ERROR( "Verbose Import is not available due to build settings" ); #endif // no validation } #else @@ -886,7 +887,7 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess ValidateDSProcess ds; ds.ExecuteOnScene( this ); if ( !pimpl->mScene ) { - DefaultLogger::get()->error( "Verbose Import: failed to revalidate data structures" ); + ASSIMP_LOG_ERROR( "Verbose Import: failed to revalidate data structures" ); } } diff --git a/code/SceneCombiner.cpp b/code/SceneCombiner.cpp index 589291131..2b6b1e19a 100644 --- a/code/SceneCombiner.cpp +++ b/code/SceneCombiner.cpp @@ -622,8 +622,8 @@ void SceneCombiner::MergeScenes(aiScene** _dest, aiScene* master, std::vectorerror(std::string("SceneCombiner: Failed to resolve attachment ") - + (*it).node->mName.data + " " + (*it).attachToNode->mName.data); + ASSIMP_LOG_ERROR_F( "SceneCombiner: Failed to resolve attachment ", (*it).node->mName.data, + " ", (*it).attachToNode->mName.data ); } } } diff --git a/code/UnrealLoader.cpp b/code/UnrealLoader.cpp index 5990ce1c5..64bfbb9e0 100644 --- a/code/UnrealLoader.cpp +++ b/code/UnrealLoader.cpp @@ -153,9 +153,9 @@ void UnrealImporter::InternReadFile( const std::string& pFile, a_path = extension+"_a.3d"; uc_path = extension+".uc"; - DefaultLogger::get()->debug("UNREAL: data file is " + d_path); - DefaultLogger::get()->debug("UNREAL: aniv file is " + a_path); - DefaultLogger::get()->debug("UNREAL: uc file is " + uc_path); + ASSIMP_LOG_DEBUG_F( "UNREAL: data file is ", d_path); + ASSIMP_LOG_DEBUG_F("UNREAL: aniv file is ", a_path); + ASSIMP_LOG_DEBUG_F("UNREAL: uc file is ", uc_path); // and open the files ... we can't live without them std::unique_ptr p(pIOHandler->Open(d_path)); @@ -179,7 +179,7 @@ void UnrealImporter::InternReadFile( const std::string& pFile, tri.mVertex[i] = d_reader.GetI2(); if (tri.mVertex[i] >= numTris) { - DefaultLogger::get()->warn("UNREAL: vertex index out of range"); + ASSIMP_LOG_WARN("UNREAL: vertex index out of range"); tri.mVertex[i] = 0; } } @@ -324,7 +324,7 @@ void UnrealImporter::InternReadFile( const std::string& pFile, } } else { - DefaultLogger::get()->error("Unable to open .uc file"); + ASSIMP_LOG_ERROR("Unable to open .uc file"); } std::vector materials; diff --git a/include/assimp/BlobIOSystem.h b/include/assimp/BlobIOSystem.h index 3c1691d5b..a0ed7209f 100644 --- a/include/assimp/BlobIOSystem.h +++ b/include/assimp/BlobIOSystem.h @@ -251,7 +251,7 @@ public: } } if (!master) { - DefaultLogger::get()->error("BlobIOSystem: no data written or master file was not closed properly."); + ASSIMP_LOG_ERROR("BlobIOSystem: no data written or master file was not closed properly."); return NULL; } From b6f29bf54f7577509ba1f6983064e267f556a8bf Mon Sep 17 00:00:00 2001 From: kimkulling Date: Thu, 19 Apr 2018 17:21:21 +0200 Subject: [PATCH 157/278] Add usage of log macros, next files. --- code/ColladaParser.cpp | 13 +++--- code/DXFHelper.h | 2 +- code/DXFLoader.cpp | 4 +- code/DeboneProcess.cpp | 4 +- code/DefaultIOSystem.cpp | 6 +-- code/FindInvalidDataProcess.cpp | 2 +- code/HMPLoader.cpp | 6 +-- code/Importer.cpp | 38 +++++++++--------- code/Importer/IFC/STEPFileReader.cpp | 2 +- code/ImproveCacheLocality.cpp | 2 +- code/JoinVerticesProcess.cpp | 2 +- code/LWOMaterial.cpp | 2 +- code/LWSLoader.cpp | 2 +- code/MD3Loader.cpp | 2 +- code/MD5Parser.cpp | 14 +++---- code/MDLLoader.cpp | 60 ++++++++++++++-------------- code/MDLMaterialLoader.cpp | 4 +- code/MS3DLoader.cpp | 4 +- code/NDOLoader.cpp | 2 +- code/NFFLoader.cpp | 8 ++-- code/ObjFileParser.cpp | 4 +- code/OgreMaterial.cpp | 6 +-- code/OgreStructs.cpp | 4 +- code/PlyParser.cpp | 4 +- code/Q3DLoader.cpp | 6 +-- code/RemoveVCProcess.cpp | 2 +- code/SIBImporter.cpp | 2 +- code/SMDLoader.cpp | 6 +-- code/SceneCombiner.cpp | 14 +++---- code/ScenePreprocessor.cpp | 12 +++--- code/SplitByBoneCountProcess.cpp | 6 +-- code/Subdivision.cpp | 4 +- code/TextureTransform.cpp | 2 +- code/ValidateDataStructure.cpp | 2 +- include/assimp/Profiler.h | 4 +- 35 files changed, 128 insertions(+), 129 deletions(-) diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index 20d6a39d5..fc283ff8c 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -2770,7 +2770,7 @@ void ColladaParser::ReadSceneNode( Node* pNode) // Reference to a light, name given in 'url' attribute int attrID = TestAttribute("url"); if (-1 == attrID) - DefaultLogger::get()->warn("Collada: Expected url attribute in element"); + ASSIMP_LOG_WARN("Collada: Expected url attribute in element"); else { const char* url = mReader->getAttributeValue( attrID); @@ -2786,7 +2786,7 @@ void ColladaParser::ReadSceneNode( Node* pNode) // Reference to a camera, name given in 'url' attribute int attrID = TestAttribute("url"); if (-1 == attrID) - DefaultLogger::get()->warn("Collada: Expected url attribute in element"); + ASSIMP_LOG_WARN("Collada: Expected url attribute in element"); else { const char* url = mReader->getAttributeValue( attrID); @@ -2873,7 +2873,7 @@ void ColladaParser::ReadMaterialVertexInputBinding( Collada::SemanticMappingTabl tbl.mMap[s] = vn; } else if( IsElement( "bind")) { - DefaultLogger::get()->warn("Collada: Found unsupported element"); + ASSIMP_LOG_WARN("Collada: Found unsupported element"); } } else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { @@ -2992,10 +2992,9 @@ void ColladaParser::ReportWarning(const char* msg,...) ai_assert(iLen > 0); va_end(args); - DefaultLogger::get()->warn("Validation warning: " + std::string(szBuffer,iLen)); + ASSIMP_LOG_WARN_F("Validation warning: ", std::string(szBuffer,iLen)); } - // ------------------------------------------------------------------------------------------------ // Skips all data until the end node of the current element void ColladaParser::SkipElement() @@ -3190,7 +3189,7 @@ aiMatrix4x4 ColladaParser::CalculateResultTransform( const std::vectorwarn( format() << "Vertex input type is empty." ); + ASSIMP_LOG_WARN("Vertex input type is empty." ); return IT_Invalid; } @@ -3209,7 +3208,7 @@ Collada::InputType ColladaParser::GetTypeForSemantic( const std::string& semanti else if( semantic == "TANGENT" || semantic == "TEXTANGENT") return IT_Tangent; - DefaultLogger::get()->warn( format() << "Unknown vertex input type \"" << semantic << "\". Ignoring." ); + ASSIMP_LOG_WARN_F( "Unknown vertex input type \"", semantic, "\". Ignoring." ); return IT_Invalid; } diff --git a/code/DXFHelper.h b/code/DXFHelper.h index 49ca2814d..00e66a0db 100644 --- a/code/DXFHelper.h +++ b/code/DXFHelper.h @@ -146,7 +146,7 @@ public: for(;splitter->length() && splitter->at(0) != '}'; splitter++, cnt++); splitter++; - DefaultLogger::get()->debug((Formatter::format("DXF: skipped over control group ("),cnt," lines)")); + ASSIMP_LOG_DEBUG((Formatter::format("DXF: skipped over control group ("),cnt," lines)")); } } catch(std::logic_error&) { ai_assert(!splitter); diff --git a/code/DXFLoader.cpp b/code/DXFLoader.cpp index 6c42d0fc2..89cc1d654 100644 --- a/code/DXFLoader.cpp +++ b/code/DXFLoader.cpp @@ -485,7 +485,7 @@ void DXFImporter::ParseBlocks(DXF::LineReader& reader, DXF::FileData& output) ++reader; } - DefaultLogger::get()->debug((Formatter::format("DXF: got "), + ASSIMP_LOG_DEBUG((Formatter::format("DXF: got "), output.blocks.size()," entries in BLOCKS" )); } @@ -567,7 +567,7 @@ void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output) ++reader; } - DefaultLogger::get()->debug((Formatter::format("DXF: got "), + ASSIMP_LOG_DEBUG((Formatter::format("DXF: got "), block.lines.size()," polylines and ", block.insertions.size() ," inserted blocks in ENTITIES" )); } diff --git a/code/DeboneProcess.cpp b/code/DeboneProcess.cpp index 33692b6a3..5a742dcf4 100644 --- a/code/DeboneProcess.cpp +++ b/code/DeboneProcess.cpp @@ -209,7 +209,7 @@ bool DeboneProcess::ConsiderMesh(const aiMesh* pMesh) if(vertexBones[vid]!=cUnowned) { if(vertexBones[vid]==i) //double entry { - DefaultLogger::get()->warn("Encountered double entry in bone weights"); + ASSIMP_LOG_WARN("Encountered double entry in bone weights"); } else //TODO: track attraction in order to break tie { @@ -281,7 +281,7 @@ void DeboneProcess::SplitMesh( const aiMesh* pMesh, std::vector< std::pair< aiMe if(vertexBones[vid]!=cUnowned) { if(vertexBones[vid]==i) //double entry { - //DefaultLogger::get()->warn("Encountered double entry in bone weights"); + ASSIMP_LOG_WARN("Encountered double entry in bone weights"); } else //TODO: track attraction in order to break tie { diff --git a/code/DefaultIOSystem.cpp b/code/DefaultIOSystem.cpp index 36c14e41d..ec0de6e3a 100644 --- a/code/DefaultIOSystem.cpp +++ b/code/DefaultIOSystem.cpp @@ -170,7 +170,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out) if (!ret) { // preserve the input path, maybe someone else is able to fix // the path before it is accessed (e.g. our file system filter) - DefaultLogger::get()->warn("Invalid path: " + std::string(in)); + ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in)); strcpy(_out, in); } @@ -179,7 +179,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out) if (!ret) { // preserve the input path, maybe someone else is able to fix // the path before it is accessed (e.g. our file system filter) - DefaultLogger::get()->warn("Invalid path: " + std::string(in)); + ASSIMP_LOG_WARN("Invalid path: ", std::string(in)); strcpy(_out, in); } } @@ -189,7 +189,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out) if(!ret) { // preserve the input path, maybe someone else is able to fix // the path before it is accessed (e.g. our file system filter) - DefaultLogger::get()->warn("Invalid path: "+std::string(in)); + ASSIMP_LOG_WARN("Invalid path: ", std::string(in)); strcpy(_out,in); } #endif diff --git a/code/FindInvalidDataProcess.cpp b/code/FindInvalidDataProcess.cpp index aac69950c..5e6b43dee 100644 --- a/code/FindInvalidDataProcess.cpp +++ b/code/FindInvalidDataProcess.cpp @@ -332,7 +332,7 @@ void FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim) i = 1; } if (1 == i) - DefaultLogger::get()->warn("Simplified dummy tracks with just one key"); + ASSIMP_LOG_WARN("Simplified dummy tracks with just one key"); } // ------------------------------------------------------------------------------------------------ diff --git a/code/HMPLoader.cpp b/code/HMPLoader.cpp index aafd3a25c..7f53f9b54 100644 --- a/code/HMPLoader.cpp +++ b/code/HMPLoader.cpp @@ -141,21 +141,21 @@ void HMPImporter::InternReadFile( const std::string& pFile, if (AI_HMP_MAGIC_NUMBER_LE_4 == iMagic || AI_HMP_MAGIC_NUMBER_BE_4 == iMagic) { - DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A4, magic word is HMP4"); + ASSIMP_LOG_DEBUG("HMP subtype: 3D GameStudio A4, magic word is HMP4"); InternReadFile_HMP4(); } // HMP5 format else if (AI_HMP_MAGIC_NUMBER_LE_5 == iMagic || AI_HMP_MAGIC_NUMBER_BE_5 == iMagic) { - DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A5, magic word is HMP5"); + ASSIMP_LOG_DEBUG("HMP subtype: 3D GameStudio A5, magic word is HMP5"); InternReadFile_HMP5(); } // HMP7 format else if (AI_HMP_MAGIC_NUMBER_LE_7 == iMagic || AI_HMP_MAGIC_NUMBER_BE_7 == iMagic) { - DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A7, magic word is HMP7"); + ASSIMP_LOG_DEBUG("HMP subtype: 3D GameStudio A7, magic word is HMP7"); InternReadFile_HMP7(); } else diff --git a/code/Importer.cpp b/code/Importer.cpp index 1b3ccf2a1..f47160c5c 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -205,7 +205,7 @@ aiReturn Importer::RegisterPPStep(BaseProcess* pImp) ASSIMP_BEGIN_EXCEPTION_REGION(); pimpl->mPostProcessingSteps.push_back(pImp); - DefaultLogger::get()->info("Registering custom post-processing step"); + ASSIMP_LOG_INFO("Registering custom post-processing step"); ASSIMP_END_EXCEPTION_REGION(aiReturn); return AI_SUCCESS; @@ -232,7 +232,7 @@ aiReturn Importer::RegisterLoader(BaseImporter* pImp) #ifdef ASSIMP_BUILD_DEBUG if (IsExtensionSupported(*it)) { - DefaultLogger::get()->warn("The file extension " + *it + " is already in use"); + ASSIMP_LOG_WARN_F("The file extension ", *it, " is already in use"); } #endif baked += *it; @@ -240,7 +240,7 @@ aiReturn Importer::RegisterLoader(BaseImporter* pImp) // add the loader pimpl->mImporter.push_back(pImp); - DefaultLogger::get()->info("Registering custom importer for these file extensions: " + baked); + ASSIMP_LOG_INFO_F("Registering custom importer for these file extensions: ", baked); ASSIMP_END_EXCEPTION_REGION(aiReturn); return AI_SUCCESS; } @@ -260,10 +260,10 @@ aiReturn Importer::UnregisterLoader(BaseImporter* pImp) if (it != pimpl->mImporter.end()) { pimpl->mImporter.erase(it); - DefaultLogger::get()->info("Unregistering custom importer: "); + ASSIMP_LOG_INFO("Unregistering custom importer: "); return AI_SUCCESS; } - DefaultLogger::get()->warn("Unable to remove custom importer: I can't find you ..."); + ASSIMP_LOG_WARN("Unable to remove custom importer: I can't find you ..."); ASSIMP_END_EXCEPTION_REGION(aiReturn); return AI_FAILURE; } @@ -283,10 +283,10 @@ aiReturn Importer::UnregisterPPStep(BaseProcess* pImp) if (it != pimpl->mPostProcessingSteps.end()) { pimpl->mPostProcessingSteps.erase(it); - DefaultLogger::get()->info("Unregistering custom post-processing step"); + ASSIMP_LOG_INFO("Unregistering custom post-processing step"); return AI_SUCCESS; } - DefaultLogger::get()->warn("Unable to remove custom post-processing step: I can't find you .."); + ASSIMP_LOG_WARN("Unable to remove custom post-processing step: I can't find you .."); ASSIMP_END_EXCEPTION_REGION(aiReturn); return AI_FAILURE; } @@ -586,7 +586,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) // a scene. In this case we need to delete the old one if (pimpl->mScene) { - DefaultLogger::get()->debug("(Deleting previous scene)"); + ASSIMP_LOG_DEBUG("(Deleting previous scene)"); FreeScene(); } @@ -617,7 +617,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) // not so bad yet ... try format auto detection. const std::string::size_type s = pFile.find_last_of('.'); if (s != std::string::npos) { - DefaultLogger::get()->info("File extension not known, trying signature-based detection"); + ASSIMP_LOG_INFO("File extension not known, trying signature-based detection"); for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) { if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, true)) { imp = pimpl->mImporter[a]; @@ -648,7 +648,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) if ( NULL != desc ) { ext = desc->mName; } - DefaultLogger::get()->info("Found a matching importer for this file format: " + ext + "." ); + ASSIMP_LOG_INFO("Found a matching importer for this file format: " + ext + "." ); pimpl->mProgressHandler->UpdateFileRead( 0, fileSize ); if (profiler) { @@ -744,7 +744,7 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) // In debug builds: run basic flag validation ai_assert(_ValidateFlags(pFlags)); - DefaultLogger::get()->info("Entering post processing pipeline"); + ASSIMP_LOG_INFO("Entering post processing pipeline"); #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS // The ValidateDS process plays an exceptional role. It isn't contained in the global @@ -768,7 +768,7 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) } #else if (pimpl->bExtraVerbose) { - DefaultLogger::get()->warn("Not a debug build, ignoring extra verbose setting"); + ASSIMP_LOG_WARN("Not a debug build, ignoring extra verbose setting"); } #endif // ! DEBUG @@ -800,7 +800,7 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) // If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step if (pimpl->bExtraVerbose) { - DefaultLogger::get()->debug("Verbose Import: re-validating data structures"); + ASSIMP_LOG_DEBUG("Verbose Import: re-validating data structures"); ValidateDSProcess ds; ds.ExecuteOnScene (this); @@ -820,7 +820,7 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) // clear any data allocated by post-process steps pimpl->mPPShared->Clean(); - DefaultLogger::get()->info("Leaving post processing pipeline"); + ASSIMP_LOG_INFO("Leaving post processing pipeline"); ASSIMP_END_EXCEPTION_REGION(const aiScene*); return pimpl->mScene; @@ -841,7 +841,7 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess } // In debug builds: run basic flag validation - DefaultLogger::get()->info( "Entering customized post processing pipeline" ); + ASSIMP_LOG_INFO( "Entering customized post processing pipeline" ); #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS // The ValidateDS process plays an exceptional role. It isn't contained in the global @@ -864,7 +864,7 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess } #else if ( pimpl->bExtraVerbose ) { - DefaultLogger::get()->warn( "Not a debug build, ignoring extra verbose setting" ); + ASSIMP_LOG_WARN( "Not a debug build, ignoring extra verbose setting" ); } #endif // ! DEBUG @@ -882,7 +882,7 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess // If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step if ( pimpl->bExtraVerbose || requestValidation ) { - DefaultLogger::get()->debug( "Verbose Import: revalidating data structures" ); + ASSIMP_LOG_DEBUG( "Verbose Import: revalidating data structures" ); ValidateDSProcess ds; ds.ExecuteOnScene( this ); @@ -893,7 +893,7 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess // clear any data allocated by post-process steps pimpl->mPPShared->Clean(); - DefaultLogger::get()->info( "Leaving customized post processing pipeline" ); + ASSIMP_LOG_INFO( "Leaving customized post processing pipeline" ); ASSIMP_END_EXCEPTION_REGION( const aiScene* ); @@ -904,7 +904,7 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess // Helper function to check whether an extension is supported by ASSIMP bool Importer::IsExtensionSupported(const char* szExtension) const { - return NULL != GetImporter(szExtension); + return nullptr != GetImporter(szExtension); } // ------------------------------------------------------------------------------------------------ diff --git a/code/Importer/IFC/STEPFileReader.cpp b/code/Importer/IFC/STEPFileReader.cpp index ba33f3928..34981d0c5 100644 --- a/code/Importer/IFC/STEPFileReader.cpp +++ b/code/Importer/IFC/STEPFileReader.cpp @@ -296,7 +296,7 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, } if ( !DefaultLogger::isNullLogger()){ - DefaultLogger::get()->debug((Formatter::format(),"STEP: got ",map.size()," object records with ", + ASSIMP_LOG_DEBUG((Formatter::format(),"STEP: got ",map.size()," object records with ", db.GetRefs().size()," inverse index entries")); } } diff --git a/code/ImproveCacheLocality.cpp b/code/ImproveCacheLocality.cpp index cc6e9db46..ef16aeac9 100644 --- a/code/ImproveCacheLocality.cpp +++ b/code/ImproveCacheLocality.cpp @@ -186,7 +186,7 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh // mesh, otherwise this value would normally be at least minimally // smaller than 3.0 ... ai_snprintf(szBuff,128,"Mesh %u: Not suitable for vcache optimization",meshNum); - DefaultLogger::get()->warn(szBuff); + ASSIMP_LOG_WARN(szBuff); return 0.f; } } diff --git a/code/JoinVerticesProcess.cpp b/code/JoinVerticesProcess.cpp index cffe74fb2..3ab5d5833 100644 --- a/code/JoinVerticesProcess.cpp +++ b/code/JoinVerticesProcess.cpp @@ -409,7 +409,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) } --a; - DefaultLogger::get()->warn("Removing bone -> no weights remaining"); + ASSIMP_LOG_WARN("Removing bone -> no weights remaining"); } } return pMesh->mNumVertices; diff --git a/code/LWOMaterial.cpp b/code/LWOMaterial.cpp index df8d328da..383d3acb7 100644 --- a/code/LWOMaterial.cpp +++ b/code/LWOMaterial.cpp @@ -164,7 +164,7 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex static_assert(sizeof(aiUVTransform)/sizeof(ai_real) == 5, "sizeof(aiUVTransform)/sizeof(ai_real) == 5"); pcMat->AddProperty(&trafo,1,AI_MATKEY_UVTRANSFORM(type,cur)); } - DefaultLogger::get()->debug("LWO2: Setting up non-UV mapping"); + ASSIMP_LOG_DEBUG("LWO2: Setting up non-UV mapping"); } // The older LWOB format does not use indirect references to clips. diff --git a/code/LWSLoader.cpp b/code/LWSLoader.cpp index 1fcc5f789..baff6ab06 100644 --- a/code/LWSLoader.cpp +++ b/code/LWSLoader.cpp @@ -105,7 +105,7 @@ void LWS::Element::Parse (const char*& buffer) if (children.back().tokens[0] == "Plugin") { - DefaultLogger::get()->debug("LWS: Skipping over plugin-specific data"); + ASSIMP_LOG_DEBUG("LWS: Skipping over plugin-specific data"); // strange stuff inside Plugin/Endplugin blocks. Needn't // follow LWS syntax, so we skip over it diff --git a/code/MD3Loader.cpp b/code/MD3Loader.cpp index e86c3e0ca..7b71ee42f 100644 --- a/code/MD3Loader.cpp +++ b/code/MD3Loader.cpp @@ -890,7 +890,7 @@ void MD3Importer::InternReadFile( const std::string& pFile, if (it != skins.textures.end()) { texture_name = &*( _texture_name = (*it).second).begin(); - DefaultLogger::get()->debug("MD3: Assigning skin texture " + (*it).second + " to surface " + pcSurfaces->NAME); + ASSIMP_LOG_DEBUG_F("MD3: Assigning skin texture ", (*it).second, " to surface ", pcSurfaces->NAME); (*it).resolved = true; // mark entry as resolved } diff --git a/code/MD5Parser.cpp b/code/MD5Parser.cpp index 5593a3a0b..d927d998a 100644 --- a/code/MD5Parser.cpp +++ b/code/MD5Parser.cpp @@ -70,7 +70,7 @@ MD5Parser::MD5Parser(char* _buffer, unsigned int _fileSize ) fileSize = _fileSize; lineNumber = 0; - DefaultLogger::get()->debug("MD5Parser begin"); + ASSIMP_LOG_DEBUG("MD5Parser begin"); // parse the file header ParseHeader(); @@ -88,7 +88,7 @@ MD5Parser::MD5Parser(char* _buffer, unsigned int _fileSize ) if ( !DefaultLogger::isNullLogger()) { char szBuffer[128]; // should be sufficiently large ::ai_snprintf(szBuffer,128,"MD5Parser end. Parsed %i sections",(int)mSections.size()); - DefaultLogger::get()->debug(szBuffer); + ASSIMP_LOG_DEBUG(szBuffer); } } @@ -243,7 +243,7 @@ bool MD5Parser::ParseSection(Section& out) // .MD5MESH parsing function MD5MeshParser::MD5MeshParser(SectionList& mSections) { - DefaultLogger::get()->debug("MD5MeshParser begin"); + ASSIMP_LOG_DEBUG("MD5MeshParser begin"); // now parse all sections for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end();iter != iterEnd;++iter){ @@ -354,14 +354,14 @@ MD5MeshParser::MD5MeshParser(SectionList& mSections) } } } - DefaultLogger::get()->debug("MD5MeshParser end"); + ASSIMP_LOG_DEBUG("MD5MeshParser end"); } // ------------------------------------------------------------------------------------------------ // .MD5ANIM parsing function MD5AnimParser::MD5AnimParser(SectionList& mSections) { - DefaultLogger::get()->debug("MD5AnimParser begin"); + ASSIMP_LOG_DEBUG("MD5AnimParser begin"); fFrameRate = 24.0f; mNumAnimatedComponents = UINT_MAX; @@ -445,14 +445,14 @@ MD5AnimParser::MD5AnimParser(SectionList& mSections) fast_atoreal_move((*iter).mGlobalValue.c_str(),fFrameRate); } } - DefaultLogger::get()->debug("MD5AnimParser end"); + ASSIMP_LOG_DEBUG("MD5AnimParser end"); } // ------------------------------------------------------------------------------------------------ // .MD5CAMERA parsing function MD5CameraParser::MD5CameraParser(SectionList& mSections) { - DefaultLogger::get()->debug("MD5CameraParser begin"); + ASSIMP_LOG_DEBUG("MD5CameraParser begin"); fFrameRate = 24.0f; for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end();iter != iterEnd;++iter) { diff --git a/code/MDLLoader.cpp b/code/MDLLoader.cpp index 3f2bb084b..aed244bc2 100644 --- a/code/MDLLoader.cpp +++ b/code/MDLLoader.cpp @@ -187,37 +187,37 @@ void MDLImporter::InternReadFile( const std::string& pFile, // Original Quake1 format if (AI_MDL_MAGIC_NUMBER_BE == iMagicWord || AI_MDL_MAGIC_NUMBER_LE == iMagicWord) { - DefaultLogger::get()->debug("MDL subtype: Quake 1, magic word is IDPO"); + ASSIMP_LOG_DEBUG("MDL subtype: Quake 1, magic word is IDPO"); iGSFileVersion = 0; InternReadFile_Quake1(); } // GameStudio A MDL2 format - used by some test models that come with 3DGS else if (AI_MDL_MAGIC_NUMBER_BE_GS3 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS3 == iMagicWord) { - DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A2, magic word is MDL2"); + ASSIMP_LOG_DEBUG("MDL subtype: 3D GameStudio A2, magic word is MDL2"); iGSFileVersion = 2; InternReadFile_Quake1(); } // GameStudio A4 MDL3 format else if (AI_MDL_MAGIC_NUMBER_BE_GS4 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS4 == iMagicWord) { - DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A4, magic word is MDL3"); + ASSIMP_LOG_DEBUG("MDL subtype: 3D GameStudio A4, magic word is MDL3"); iGSFileVersion = 3; InternReadFile_3DGS_MDL345(); } // GameStudio A5+ MDL4 format else if (AI_MDL_MAGIC_NUMBER_BE_GS5a == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS5a == iMagicWord) { - DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A4, magic word is MDL4"); + ASSIMP_LOG_DEBUG("MDL subtype: 3D GameStudio A4, magic word is MDL4"); iGSFileVersion = 4; InternReadFile_3DGS_MDL345(); } // GameStudio A5+ MDL5 format else if (AI_MDL_MAGIC_NUMBER_BE_GS5b == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS5b == iMagicWord) { - DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A5, magic word is MDL5"); + ASSIMP_LOG_DEBUG("MDL subtype: 3D GameStudio A5, magic word is MDL5"); iGSFileVersion = 5; InternReadFile_3DGS_MDL345(); } // GameStudio A7 MDL7 format else if (AI_MDL_MAGIC_NUMBER_BE_GS7 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS7 == iMagicWord) { - DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A7, magic word is MDL7"); + ASSIMP_LOG_DEBUG("MDL subtype: 3D GameStudio A7, magic word is MDL7"); iGSFileVersion = 7; InternReadFile_3DGS_MDL7(); } @@ -225,7 +225,7 @@ void MDLImporter::InternReadFile( const std::string& pFile, else if (AI_MDL_MAGIC_NUMBER_BE_HL2a == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2a == iMagicWord || AI_MDL_MAGIC_NUMBER_BE_HL2b == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2b == iMagicWord) { - DefaultLogger::get()->debug("MDL subtype: Source(tm) Engine, magic word is IDST/IDSQ"); + ASSIMP_LOG_DEBUG("MDL subtype: Source(tm) Engine, magic word is IDST/IDSQ"); iGSFileVersion = 0; InternReadFile_HL2(); } @@ -258,7 +258,7 @@ void MDLImporter::SizeCheck(const void* szPos) } // ------------------------------------------------------------------------------------------------ -// Just for debgging purposes +// Just for debugging purposes void MDLImporter::SizeCheck(const void* szPos, const char* szFile, unsigned int iLine) { ai_assert(NULL != szFile); @@ -298,20 +298,20 @@ void MDLImporter::ValidateHeader_Quake1(const MDL::Header* pcHeader) if (!this->iGSFileVersion) { if (pcHeader->num_verts > AI_MDL_MAX_VERTS) - DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_VERTS vertices"); + ASSIMP_LOG_WARN("Quake 1 MDL model has more than AI_MDL_MAX_VERTS vertices"); if (pcHeader->num_tris > AI_MDL_MAX_TRIANGLES) - DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_TRIANGLES triangles"); + ASSIMP_LOG_WARN("Quake 1 MDL model has more than AI_MDL_MAX_TRIANGLES triangles"); if (pcHeader->num_frames > AI_MDL_MAX_FRAMES) - DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_FRAMES frames"); + ASSIMP_LOG_WARN("Quake 1 MDL model has more than AI_MDL_MAX_FRAMES frames"); // (this does not apply for 3DGS MDLs) if (!this->iGSFileVersion && pcHeader->version != AI_MDL_VERSION) - DefaultLogger::get()->warn("Quake 1 MDL model has an unknown version: AI_MDL_VERSION (=6) is " + ASSIMP_LOG_WARN("Quake 1 MDL model has an unknown version: AI_MDL_VERSION (=6) is " "the expected file format version"); if(pcHeader->num_skins && (!pcHeader->skinwidth || !pcHeader->skinheight)) - DefaultLogger::get()->warn("Skin width or height are 0"); + ASSIMP_LOG_WARN("Skin width or height are 0"); } } @@ -692,7 +692,7 @@ void MDLImporter::InternReadFile_3DGS_MDL345( ) unsigned int iIndex = pcTriangles->index_xyz[c]; if (iIndex >= (unsigned int)pcHeader->num_verts) { iIndex = pcHeader->num_verts-1; - DefaultLogger::get()->warn("Index overflow in MDLn vertex list"); + ASSIMP_LOG_WARN("Index overflow in MDLn vertex list"); } aiVector3D& vec = pcMesh->mVertices[iCurrent]; @@ -747,7 +747,7 @@ void MDLImporter::InternReadFile_3DGS_MDL345( ) unsigned int iIndex = pcTriangles->index_xyz[c]; if (iIndex >= (unsigned int)pcHeader->num_verts) { iIndex = pcHeader->num_verts-1; - DefaultLogger::get()->warn("Index overflow in MDLn vertex list"); + ASSIMP_LOG_WARN("Index overflow in MDLn vertex list"); } aiVector3D& vec = pcMesh->mVertices[iCurrent]; @@ -798,7 +798,7 @@ void MDLImporter::ImportUVCoordinate_3DGS_MDL345( // validate UV indices if (iIndex >= (unsigned int) pcHeader->synctype) { iIndex = pcHeader->synctype-1; - DefaultLogger::get()->warn("Index overflow in MDLn UV coord list"); + ASSIMP_LOG_WARN("Index overflow in MDLn UV coord list"); } float s = (float)pcSrc[iIndex].u; @@ -835,7 +835,7 @@ void MDLImporter::CalculateUVCoordinates_MDL5() iWidth = (unsigned int)*piPtr; if (!iHeight || !iWidth) { - DefaultLogger::get()->warn("Either the width or the height of the " + ASSIMP_LOG_WARN("Either the width or the height of the " "embedded DDS texture is zero. Unable to compute final texture " "coordinates. The texture coordinates remain in their original " "0-x/0-y (x,y = texture size) range."); @@ -988,7 +988,7 @@ MDL::IntBone_MDL7** MDLImporter::LoadBones_3DGS_MDL7() AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_32_CHARS != pcHeader->bone_stc_size && AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE != pcHeader->bone_stc_size) { - DefaultLogger::get()->warn("Unknown size of bone data structure"); + ASSIMP_LOG_WARN("Unknown size of bone data structure"); return NULL; } @@ -1026,7 +1026,7 @@ void MDLImporter::ReadFaces_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo, if(iIndex > (unsigned int)groupInfo.pcGroup->numverts) { // (we might need to read this section a second time - to process frame vertices correctly) pcGroupTris->v_index[c] = iIndex = groupInfo.pcGroup->numverts-1; - DefaultLogger::get()->warn("Index overflow in MDL7 vertex list"); + DASSIMP_LOG_WARN("Index overflow in MDL7 vertex list"); } // write the output face index @@ -1071,7 +1071,7 @@ void MDLImporter::ReadFaces_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo, iIndex = pcGroupTris->skinsets[0].st_index[c]; if(iIndex > (unsigned int)groupInfo.pcGroup->num_stpts) { iIndex = groupInfo.pcGroup->num_stpts-1; - DefaultLogger::get()->warn("Index overflow in MDL7 UV coordinate list (#1)"); + ASSIMP_LOG_WARN("Index overflow in MDL7 UV coordinate list (#1)"); } float u = groupInfo.pcGroupUVs[iIndex].u; @@ -1098,7 +1098,7 @@ void MDLImporter::ReadFaces_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo, iIndex = pcGroupTris->skinsets[1].st_index[c]; if(iIndex > (unsigned int)groupInfo.pcGroup->num_stpts) { iIndex = groupInfo.pcGroup->num_stpts-1; - DefaultLogger::get()->warn("Index overflow in MDL7 UV coordinate list (#2)"); + ASSIMP_LOG_WARN("Index overflow in MDL7 UV coordinate list (#2)"); } float u = groupInfo.pcGroupUVs[ iIndex ].u; @@ -1153,7 +1153,7 @@ bool MDLImporter::ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInf frame.pcFrame->transmatrix_count * pcHeader->bonetrans_stc_size; if (((const char*)szCurrent - (const char*)pcHeader) + iAdd > (unsigned int)pcHeader->data_size) { - DefaultLogger::get()->warn("Index overflow in frame area. " + ASSIMP_LOG_WARN("Index overflow in frame area. " "Ignoring all frames and all further mesh groups, too."); // don't parse more groups if we can't even read one @@ -1171,7 +1171,7 @@ bool MDLImporter::ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInf uint16_t iIndex = _AI_MDL7_ACCESS(pcFrameVertices,qq,pcHeader->framevertex_stc_size,MDL::Vertex_MDL7).vertindex; AI_SWAP2(iIndex); if (iIndex >= groupInfo.pcGroup->numverts) { - DefaultLogger::get()->warn("Invalid vertex index in frame vertex section"); + ASSIMP_LOG_WARN("Invalid vertex index in frame vertex section"); continue; } @@ -1257,7 +1257,7 @@ void MDLImporter::SortByMaterials_3DGS_MDL7( // sometimes MED writes -1, but normally only if there is only // one skin assigned. No warning in this case if(0xFFFFFFFF != groupData.pcFaces[iFace].iMatIndex[0]) - DefaultLogger::get()->warn("Index overflow in MDL7 material list [#0]"); + ASSIMP_LOG_WARN("Index overflow in MDL7 material list [#0]"); } else splitGroupData.aiSplit[groupData.pcFaces[iFace]. iMatIndex[0]]->push_back(iFace); @@ -1282,7 +1282,7 @@ void MDLImporter::SortByMaterials_3DGS_MDL7( // sometimes MED writes -1, but normally only if there is only // one skin assigned. No warning in this case if(UINT_MAX != iMatIndex) - DefaultLogger::get()->warn("Index overflow in MDL7 material list [#1]"); + ASSIMP_LOG_WARN("Index overflow in MDL7 material list [#1]"); iMatIndex = iNumMaterials-1; } unsigned int iMatIndex2 = groupData.pcFaces[iFace].iMatIndex[1]; @@ -1292,7 +1292,7 @@ void MDLImporter::SortByMaterials_3DGS_MDL7( if (iMatIndex2 >= iNumMaterials) { // sometimes MED writes -1, but normally only if there is only // one skin assigned. No warning in this case - DefaultLogger::get()->warn("Index overflow in MDL7 material list [#2]"); + ASSIMP_LOG_WARN("Index overflow in MDL7 material list [#2]"); iMatIndex2 = iNumMaterials-1; } @@ -1414,7 +1414,7 @@ void MDLImporter::InternReadFile_3DGS_MDL7( ) if (1 != groupInfo.pcGroup->typ) { // Not a triangle-based mesh - DefaultLogger::get()->warn("[3DGS MDL7] Not a triangle mesh group. Continuing happily"); + ASSIMP_LOG_WARN("[3DGS MDL7] Not a triangle mesh group. Continuing happily"); } // store the name of the group @@ -1516,7 +1516,7 @@ void MDLImporter::InternReadFile_3DGS_MDL7( ) sharedData.abNeedMaterials[qq] = true; } } - else DefaultLogger::get()->warn("[3DGS MDL7] Mesh group consists of 0 " + else ASSIMP_LOG_WARN("[3DGS MDL7] Mesh group consists of 0 " "vertices or faces. It will be skipped."); // process all frames and generate output meshes @@ -1664,7 +1664,7 @@ void MDLImporter::ParseBoneTrafoKeys_3DGS_MDL7( // read all transformation matrices for (unsigned int iTrafo = 0; iTrafo < frame.pcFrame->transmatrix_count;++iTrafo) { if(pcBoneTransforms->bone_index >= pcHeader->bones_num) { - DefaultLogger::get()->warn("Index overflow in frame area. " + ASSIMP_LOG_WARN("Index overflow in frame area. " "Unable to parse this bone transformation"); } else { @@ -1676,7 +1676,7 @@ void MDLImporter::ParseBoneTrafoKeys_3DGS_MDL7( } } else { - DefaultLogger::get()->warn("Ignoring animation keyframes in groups != 0"); + ASSIMP_LOG_WARN("Ignoring animation keyframes in groups != 0"); } } } diff --git a/code/MDLMaterialLoader.cpp b/code/MDLMaterialLoader.cpp index d50957094..8955455ef 100644 --- a/code/MDLMaterialLoader.cpp +++ b/code/MDLMaterialLoader.cpp @@ -531,7 +531,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7( // ***** REFERENCE TO EXTERNAL FILE ***** if (1 != iHeight) { - DefaultLogger::get()->warn("Found a reference to an external texture, " + ASSIMP_LOG_WARN("Found a reference to an external texture, " "but texture height is not equal to 1, which is not supported by MED"); } @@ -552,7 +552,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7( pcNew.reset(new aiTexture()); if (!iHeight || !iWidth) { - DefaultLogger::get()->warn("Found embedded texture, but its width " + ASSIMP_LOG_WARN("Found embedded texture, but its width " "an height are both 0. Is this a joke?"); // generate an empty chess pattern diff --git a/code/MS3DLoader.cpp b/code/MS3DLoader.cpp index 09b3be6e1..869c41afb 100644 --- a/code/MS3DLoader.cpp +++ b/code/MS3DLoader.cpp @@ -142,7 +142,7 @@ void MS3DImporter :: ReadComments(StreamReaderLE& stream, std::vector& outp) stream >> index >> clength; if(index >= outp.size()) { - DefaultLogger::get()->warn("MS3D: Invalid index in comment section"); + ASSIMP_LOG_WARN("MS3D: Invalid index in comment section"); } else if (clength > stream.GetRemainingSize()) { throw DeadlyImportError("MS3D: Failure reading comment, length field is out of range"); @@ -408,7 +408,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile, // 2 ------------ convert to proper aiXX data structures ----------------------------------- if (need_default && materials.size()) { - DefaultLogger::get()->warn("MS3D: Found group with no material assigned, spawning default material"); + ASSIMP_LOG_WARN("MS3D: Found group with no material assigned, spawning default material"); // if one of the groups has no material assigned, but there are other // groups with materials, a default material needs to be added ( // scenepreprocessor adds a default material only if nummat==0). diff --git a/code/NDOLoader.cpp b/code/NDOLoader.cpp index b09fc1e2d..1e6c1e2ca 100644 --- a/code/NDOLoader.cpp +++ b/code/NDOLoader.cpp @@ -141,7 +141,7 @@ void NDOImporter::InternReadFile( const std::string& pFile, DefaultLogger::get()->info("NDO file format is 1.2"); } else { - DefaultLogger::get()->warn(std::string("Unrecognized nendo file format version, continuing happily ... :") + (head+6)); + ASSIMP_LOG_WARN(std::string("Unrecognized nendo file format version, continuing happily ... :") + (head+6)); } reader.IncPtr(2); /* skip flags */ diff --git a/code/NFFLoader.cpp b/code/NFFLoader.cpp index acd057d90..39f336112 100644 --- a/code/NFFLoader.cpp +++ b/code/NFFLoader.cpp @@ -125,7 +125,7 @@ const aiImporterDesc* NFFImporter::GetInfo () const do \ { \ if (!GetNextLine(buffer,line)) \ - {DefaultLogger::get()->warn("NFF2: Unexpected EOF, can't read next token");break;} \ + {ASSIMP_LOG_WARN("NFF2: Unexpected EOF, can't read next token");break;} \ SkipSpaces(line,&sz); \ } \ while(IsLineEnd(*sz)) @@ -346,7 +346,7 @@ void NFFImporter::InternReadFile( const std::string& pFile, sz3 = sz; while (!IsSpaceOrNewLine(*sz))++sz; const unsigned int diff = (unsigned int)(sz-sz3); - if (!diff)DefaultLogger::get()->warn("NFF2: Found empty mtable token"); + if (!diff)ASSIMP_LOG_WARN("NFF2: Found empty mtable token"); else { // The material table has the file extension .mat. @@ -551,11 +551,11 @@ void NFFImporter::InternReadFile( const std::string& pFile, case 'u': case 'U': - DefaultLogger::get()->warn("Unsupported NFF2 texture attribute: trans"); + ASSIMP_LOG_WARN("Unsupported NFF2 texture attribute: trans"); }; if (!sz[1] || '_' != sz[2]) { - DefaultLogger::get()->warn("NFF2: Expected underscore after texture attributes"); + ASSIMP_LOG_WARN("NFF2: Expected underscore after texture attributes"); continue; } const char* sz2 = sz+3; diff --git a/code/ObjFileParser.cpp b/code/ObjFileParser.cpp index 7cd2d36c2..004778259 100644 --- a/code/ObjFileParser.cpp +++ b/code/ObjFileParser.cpp @@ -603,7 +603,7 @@ void ObjFileParser::getMaterialLib() { // Check if directive is valid. if ( 0 == strMatName.length() ) { - DefaultLogger::get()->warn( "OBJ: no name for material library specified." ); + ASSIMP_LOG_WARN( "OBJ: no name for material library specified." ); return; } @@ -660,7 +660,7 @@ void ObjFileParser::getNewMaterial() { std::map::iterator it = m_pModel->m_MaterialMap.find( strMat ); if ( it == m_pModel->m_MaterialMap.end() ) { // Show a warning, if material was not found - DefaultLogger::get()->warn("OBJ: Unsupported material requested: " + strMat); + ASSIMP_LOG_WARN("OBJ: Unsupported material requested: " + strMat); m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial; } else { // Set new material diff --git a/code/OgreMaterial.cpp b/code/OgreMaterial.cpp index c20c8fa6f..f0fb515d8 100644 --- a/code/OgreMaterial.cpp +++ b/code/OgreMaterial.cpp @@ -186,7 +186,7 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste std::unique_ptr stream(materialFile); if (stream->FileSize() == 0) { - DefaultLogger::get()->warn(Formatter::format() << "Source file for material '" << materialName << "' is empty (size is 0 bytes)"); + ASSIMP_LOG_WARN(Formatter::format() << "Source file for material '" << materialName << "' is empty (size is 0 bytes)"); return 0; } @@ -569,12 +569,12 @@ bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstr if (textureRef.empty()) { - DefaultLogger::get()->warn("Texture reference is empty, ignoring texture_unit."); + ASSIMP_LOG_WARN("Texture reference is empty, ignoring texture_unit."); return false; } if (textureType == aiTextureType_NONE) { - DefaultLogger::get()->warn("Failed to detect texture type for '" + textureRef + "', ignoring texture_unit."); + ASSIMP_LOG_WARN("Failed to detect texture type for '" + textureRef + "', ignoring texture_unit."); return false; } diff --git a/code/OgreStructs.cpp b/code/OgreStructs.cpp index 0f3e2fa97..b2ad8e089 100644 --- a/code/OgreStructs.cpp +++ b/code/OgreStructs.cpp @@ -611,7 +611,7 @@ aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent) } else { - DefaultLogger::get()->warn(Formatter::format() << "Ogre imported UV0 type " << uv1Element->TypeToString() << " is not compatible with Assimp. Ignoring UV."); + ASSIMP_LOG_WARN(Formatter::format() << "Ogre imported UV0 type " << uv1Element->TypeToString() << " is not compatible with Assimp. Ignoring UV."); uv1 = 0; } } @@ -624,7 +624,7 @@ aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent) } else { - DefaultLogger::get()->warn(Formatter::format() << "Ogre imported UV0 type " << uv2Element->TypeToString() << " is not compatible with Assimp. Ignoring UV."); + ASSIMP_LOG_WARN(Formatter::format() << "Ogre imported UV0 type " << uv2Element->TypeToString() << " is not compatible with Assimp. Ignoring UV."); uv2 = 0; } } diff --git a/code/PlyParser.cpp b/code/PlyParser.cpp index 672ac9bde..b6bd60f9f 100644 --- a/code/PlyParser.cpp +++ b/code/PlyParser.cpp @@ -787,7 +787,7 @@ bool PLY::ElementInstance::ParseInstance(const char* &pCur, { if (!(PLY::PropertyInstance::ParseInstance(pCur, &(*a), &(*i)))) { - DefaultLogger::get()->warn("Unable to parse property instance. " + ASSIMP_LOG_WARN("Unable to parse property instance. " "Skipping this element instance"); PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a).eType); @@ -819,7 +819,7 @@ bool PLY::ElementInstance::ParseInstanceBinary( { if (!(PLY::PropertyInstance::ParseInstanceBinary(streamBuffer, buffer, pCur, bufferSize, &(*a), &(*i), p_bBE))) { - DefaultLogger::get()->warn("Unable to parse binary property instance. " + ASSIMP_LOG_WARN("Unable to parse binary property instance. " "Skipping this element instance"); (*i).avList.push_back(PLY::PropertyInstance::DefaultValue((*a).eType)); diff --git a/code/Q3DLoader.cpp b/code/Q3DLoader.cpp index 9495713a8..ebb80d537 100644 --- a/code/Q3DLoader.cpp +++ b/code/Q3DLoader.cpp @@ -433,7 +433,7 @@ outer: { if ((*fit).mat >= materials.size()) { - DefaultLogger::get()->warn("Quick3D: Material index overflow"); + ASSIMP_LOG_WARN("Quick3D: Material index overflow"); (*fit).mat = 0; } if (fidx[(*fit).mat].empty())++pScene->mNumMeshes; @@ -528,7 +528,7 @@ outer: { if (face.indices[n] >= m.verts.size()) { - DefaultLogger::get()->warn("Quick3D: Vertex index overflow"); + ASSIMP_LOG_WARN("Quick3D: Vertex index overflow"); face.indices[n] = 0; } @@ -561,7 +561,7 @@ outer: { if (face.uvindices[n] >= m.uv.size()) { - DefaultLogger::get()->warn("Quick3D: Texture coordinate index overflow"); + ASSIMP_LOG_WARN("Quick3D: Texture coordinate index overflow"); face.uvindices[n] = 0; } *uv = m.uv[face.uvindices[n]]; diff --git a/code/RemoveVCProcess.cpp b/code/RemoveVCProcess.cpp index 1c4975e35..ddb0023cc 100644 --- a/code/RemoveVCProcess.cpp +++ b/code/RemoveVCProcess.cpp @@ -242,7 +242,7 @@ void RemoveVCProcess::SetupProperties(const Importer* pImp) configDeleteFlags = pImp->GetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS,0x0); if (!configDeleteFlags) { - DefaultLogger::get()->warn("RemoveVCProcess: AI_CONFIG_PP_RVC_FLAGS is zero."); + ASSIMP_LOG_WARN("RemoveVCProcess: AI_CONFIG_PP_RVC_FLAGS is zero."); } } diff --git a/code/SIBImporter.cpp b/code/SIBImporter.cpp index 97df708ba..5c8c717b5 100644 --- a/code/SIBImporter.cpp +++ b/code/SIBImporter.cpp @@ -173,7 +173,7 @@ static void UnknownChunk(StreamReaderLE* /*stream*/, const SIBChunk& chunk) static_cast(chunk.Tag & 0xff), '\0' }; - DefaultLogger::get()->warn((Formatter::format(), "SIB: Skipping unknown '",temp,"' chunk.")); + ASSIMP_LOG_WARN((Formatter::format(), "SIB: Skipping unknown '",temp,"' chunk.")); } // Reads a UTF-16LE string and returns it at UTF-8. diff --git a/code/SMDLoader.cpp b/code/SMDLoader.cpp index ab7146daa..4f9ed5c1c 100644 --- a/code/SMDLoader.cpp +++ b/code/SMDLoader.cpp @@ -182,7 +182,7 @@ void SMDImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS { if (!(*i).mName.length()) { - DefaultLogger::get()->warn("SMD: Not all bones have been initialized"); + ASSIMP_LOG_WARN("SMD: Not all bones have been initialized"); break; } } @@ -230,7 +230,7 @@ void SMDImporter::LogWarning(const char* msg) char szTemp[1024]; ai_assert(strlen(msg) < 1000); ai_snprintf(szTemp,1024,"Line %u: %s",iLineNumber,msg); - DefaultLogger::get()->warn(szTemp); + ASSIMP_LOG_WARN(szTemp); } // ------------------------------------------------------------------------------------------------ @@ -715,7 +715,7 @@ void SMDImporter::ParseFile() if(!SkipSpaces(szCurrent,&szCurrent)) break; if (1 != strtoul10(szCurrent,&szCurrent)) { - DefaultLogger::get()->warn("SMD.version is not 1. This " + ASSIMP_LOG_WARN("SMD.version is not 1. This " "file format is not known. Continuing happily ..."); } continue; diff --git a/code/SceneCombiner.cpp b/code/SceneCombiner.cpp index 2b6b1e19a..d72477f50 100644 --- a/code/SceneCombiner.cpp +++ b/code/SceneCombiner.cpp @@ -75,7 +75,7 @@ void PrefixString(aiString& string,const char* prefix, unsigned int len) { return; if (len+string.length>=MAXLEN-1) { - DefaultLogger::get()->debug("Can't add an unique prefix because the string is too long"); + ASSIMP_LOG_DEBUG("Can't add an unique prefix because the string is too long"); ai_assert(false); return; } @@ -727,7 +727,7 @@ void SceneCombiner::MergeBones(aiMesh* out,std::vector::const_iterator // NOTE: different offset matrices for bones with equal names // are - at the moment - not handled correctly. if (wmit != (*it).pSrcBones.begin() && pc->mOffsetMatrix != (*wmit).first->mOffsetMatrix) { - DefaultLogger::get()->warn("Bones with equal names but different offset matrices can't be joined at the moment"); + ASSIMP_LOG_WARN("Bones with equal names but different offset matrices can't be joined at the moment"); continue; } pc->mOffsetMatrix = (*wmit).first->mOffsetMatrix; @@ -796,7 +796,7 @@ void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/, if ((*it)->mVertices) { ::memcpy(pv2,(*it)->mVertices,(*it)->mNumVertices*sizeof(aiVector3D)); } - else DefaultLogger::get()->warn("JoinMeshes: Positions expected but input mesh contains no positions"); + else ASSIMP_LOG_WARN("JoinMeshes: Positions expected but input mesh contains no positions"); pv2 += (*it)->mNumVertices; } } @@ -808,7 +808,7 @@ void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/, if ((*it)->mNormals) { ::memcpy(pv2,(*it)->mNormals,(*it)->mNumVertices*sizeof(aiVector3D)); } else { - DefaultLogger::get()->warn( "JoinMeshes: Normals expected but input mesh contains no normals" ); + ASSIMP_LOG_WARN( "JoinMeshes: Normals expected but input mesh contains no normals" ); } pv2 += (*it)->mNumVertices; } @@ -824,7 +824,7 @@ void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/, ::memcpy(pv2, (*it)->mTangents, (*it)->mNumVertices*sizeof(aiVector3D)); ::memcpy(pv2b,(*it)->mBitangents,(*it)->mNumVertices*sizeof(aiVector3D)); } else { - DefaultLogger::get()->warn( "JoinMeshes: Tangents expected but input mesh contains no tangents" ); + ASSIMP_LOG_WARN( "JoinMeshes: Tangents expected but input mesh contains no tangents" ); } pv2 += (*it)->mNumVertices; pv2b += (*it)->mNumVertices; @@ -840,7 +840,7 @@ void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/, if ((*it)->mTextureCoords[n]) { ::memcpy(pv2,(*it)->mTextureCoords[n],(*it)->mNumVertices*sizeof(aiVector3D)); } else { - DefaultLogger::get()->warn( "JoinMeshes: UVs expected but input mesh contains no UVs" ); + ASSIMP_LOG_WARN( "JoinMeshes: UVs expected but input mesh contains no UVs" ); } pv2 += (*it)->mNumVertices; } @@ -854,7 +854,7 @@ void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/, if ((*it)->mColors[n]) { ::memcpy(pv2,(*it)->mColors[n],(*it)->mNumVertices*sizeof(aiColor4D)); } else { - DefaultLogger::get()->warn( "JoinMeshes: VCs expected but input mesh contains no VCs" ); + ASSIMP_LOG_WARN( "JoinMeshes: VCs expected but input mesh contains no VCs" ); } pv2 += (*it)->mNumVertices; } diff --git a/code/ScenePreprocessor.cpp b/code/ScenePreprocessor.cpp index 2da890a84..eff6ecc6e 100644 --- a/code/ScenePreprocessor.cpp +++ b/code/ScenePreprocessor.cpp @@ -81,7 +81,7 @@ void ScenePreprocessor::ProcessScene () name.Set(AI_DEFAULT_MATERIAL_NAME); helper->AddProperty(&name,AI_MATKEY_NAME); - DefaultLogger::get()->debug("ScenePreprocessor: Adding default material \'" AI_DEFAULT_MATERIAL_NAME "\'"); + ASSIMP_LOG_DEBUG("ScenePreprocessor: Adding default material \'" AI_DEFAULT_MATERIAL_NAME "\'"); for (unsigned int i = 0; i < scene->mNumMeshes;++i) { scene->mMeshes[i]->mMaterialIndex = scene->mNumMaterials; @@ -122,7 +122,7 @@ void ScenePreprocessor::ProcessMesh (aiMesh* mesh) break; } if (p == end) { - DefaultLogger::get()->warn("ScenePreprocessor: UVs are declared to be 3D but they're obviously not. Reverting to 2D."); + ASSIMP_LOG_WARN("ScenePreprocessor: UVs are declared to be 3D but they're obviously not. Reverting to 2D."); mesh->mNumUVComponents[i] = 2; } } @@ -224,7 +224,7 @@ void ScenePreprocessor::ProcessAnimation (aiAnimation* anim) q.mTime = 0.; q.mValue = rotation; - DefaultLogger::get()->debug("ScenePreprocessor: Dummy rotation track has been generated"); + ASSIMP_LOG_DEBUG("ScenePreprocessor: Dummy rotation track has been generated"); } // No scaling keys? Generate a dummy track @@ -236,7 +236,7 @@ void ScenePreprocessor::ProcessAnimation (aiAnimation* anim) q.mTime = 0.; q.mValue = scaling; - DefaultLogger::get()->debug("ScenePreprocessor: Dummy scaling track has been generated"); + ASSIMP_LOG_DEBUG("ScenePreprocessor: Dummy scaling track has been generated"); } // No position keys? Generate a dummy track @@ -248,14 +248,14 @@ void ScenePreprocessor::ProcessAnimation (aiAnimation* anim) q.mTime = 0.; q.mValue = position; - DefaultLogger::get()->debug("ScenePreprocessor: Dummy position track has been generated"); + ASSIMP_LOG_DEBUG("ScenePreprocessor: Dummy position track has been generated"); } } } } if (anim->mDuration == -1.) { - DefaultLogger::get()->debug("ScenePreprocessor: Setting animation duration"); + ASSIMP_LOG_DEBUG("ScenePreprocessor: Setting animation duration"); anim->mDuration = last - std::min( first, 0. ); } } diff --git a/code/SplitByBoneCountProcess.cpp b/code/SplitByBoneCountProcess.cpp index 105ee517d..b33b6d95c 100644 --- a/code/SplitByBoneCountProcess.cpp +++ b/code/SplitByBoneCountProcess.cpp @@ -88,7 +88,7 @@ void SplitByBoneCountProcess::SetupProperties(const Importer* pImp) // Executes the post processing step on the given imported data. void SplitByBoneCountProcess::Execute( aiScene* pScene) { - DefaultLogger::get()->debug("SplitByBoneCountProcess begin"); + ASSIMP_LOG_DEBUG("SplitByBoneCountProcess begin"); // early out bool isNecessary = false; @@ -98,7 +98,7 @@ void SplitByBoneCountProcess::Execute( aiScene* pScene) if( !isNecessary ) { - DefaultLogger::get()->debug( format() << "SplitByBoneCountProcess early-out: no meshes with more than " << mMaxBoneCount << " bones." ); + ASSIMP_LOG_DEBUG( format() << "SplitByBoneCountProcess early-out: no meshes with more than " << mMaxBoneCount << " bones." ); return; } @@ -146,7 +146,7 @@ void SplitByBoneCountProcess::Execute( aiScene* pScene) // recurse through all nodes and translate the node's mesh indices to fit the new mesh array UpdateNode( pScene->mRootNode); - DefaultLogger::get()->debug( format() << "SplitByBoneCountProcess end: split " << mSubMeshIndices.size() << " meshes into " << meshes.size() << " submeshes." ); + ASSIMP_LOG_DEBUG( format() << "SplitByBoneCountProcess end: split " << mSubMeshIndices.size() << " meshes into " << meshes.size() << " submeshes." ); } // ------------------------------------------------------------------------------------------------ diff --git a/code/Subdivision.cpp b/code/Subdivision.cpp index 450e03883..f2e480db1 100644 --- a/code/Subdivision.cpp +++ b/code/Subdivision.cpp @@ -346,7 +346,7 @@ void CatmullClarkSubdivider::InternSubdivide ( ai_snprintf(tmp, 512, "Catmull-Clark Subdivider: got %u bad edges touching only one face (totally %u edges). ", bad_cnt,static_cast(edges.size())); - DefaultLogger::get()->debug(tmp); + DASSIMP_LOG_DEBUG(tmp); }} // --------------------------------------------------------------------- @@ -404,7 +404,7 @@ void CatmullClarkSubdivider::InternSubdivide ( } ai_assert(haveit); if (!haveit) { - DefaultLogger::get()->debug("Catmull-Clark Subdivider: Index not used"); + ASSIMP_LOG_DEBUG("Catmull-Clark Subdivider: Index not used"); } break; } diff --git a/code/TextureTransform.cpp b/code/TextureTransform.cpp index 79914b898..62bbadd08 100644 --- a/code/TextureTransform.cpp +++ b/code/TextureTransform.cpp @@ -331,7 +331,7 @@ void TextureTransformStep::Execute( aiScene* pScene) } if (mesh->mNumUVComponents[info.uvIndex] >= 3){ - DefaultLogger::get()->warn("UV transformations on 3D mapping channels are not supported"); + ASSIMP_LOG_WARN("UV transformations on 3D mapping channels are not supported"); continue; } diff --git a/code/ValidateDataStructure.cpp b/code/ValidateDataStructure.cpp index 045776204..20b348763 100644 --- a/code/ValidateDataStructure.cpp +++ b/code/ValidateDataStructure.cpp @@ -106,7 +106,7 @@ void ValidateDSProcess::ReportWarning(const char* msg,...) ai_assert(iLen > 0); va_end(args); - DefaultLogger::get()->warn("Validation warning: " + std::string(szBuffer,iLen)); + ASSIMP_LOG_WARN("Validation warning: " + std::string(szBuffer,iLen)); } // ------------------------------------------------------------------------------------------------ diff --git a/include/assimp/Profiler.h b/include/assimp/Profiler.h index 272085ea5..da5af2726 100644 --- a/include/assimp/Profiler.h +++ b/include/assimp/Profiler.h @@ -72,7 +72,7 @@ public: /** Start a named timer */ void BeginRegion(const std::string& region) { regions[region] = std::chrono::system_clock::now(); - DefaultLogger::get()->debug((format("START `"),region,"`")); + ASSIMP_LOG_DEBUG((format("START `"),region,"`")); } @@ -84,7 +84,7 @@ public: } std::chrono::duration elapsedSeconds = std::chrono::system_clock::now() - regions[region]; - DefaultLogger::get()->debug((format("END `"),region,"`, dt= ", elapsedSeconds.count()," s")); + ASSIMP_LOG_DEBUG((format("END `"),region,"`, dt= ", elapsedSeconds.count()," s")); } private: From 0e15b25cd132f23e8bcf48314500f88cfdd0321a Mon Sep 17 00:00:00 2001 From: kimkulling Date: Fri, 20 Apr 2018 16:23:24 +0200 Subject: [PATCH 158/278] Next log call changes. --- code/AMFImporter.cpp | 2 +- code/AMFImporter.hpp | 12 ------ code/COBLoader.cpp | 8 ++-- code/CSMLoader.cpp | 2 +- code/DXFLoader.cpp | 35 +++++++--------- code/Exporter.cpp | 2 +- code/FBXDocument.cpp | 2 +- code/FBXDocumentUtil.cpp | 2 +- code/FBXExporter.cpp | 6 +-- code/IRRLoader.cpp | 56 ++++++++++++------------- code/IRRMeshLoader.cpp | 18 ++++---- code/IRRShared.cpp | 25 +++++------ code/Importer.cpp | 50 +++++++++------------- code/Importer/IFC/STEPFileReader.cpp | 18 ++++---- code/LWOBLoader.cpp | 36 +++++++++------- code/LWOLoader.cpp | 63 +++++++++++++++------------- code/LWOLoader.h | 2 +- code/LWOMaterial.cpp | 38 ++++++++--------- code/LWSLoader.cpp | 40 +++++++++--------- code/MD2Loader.cpp | 20 ++++----- code/MD3Loader.cpp | 55 ++++++++++++------------ code/MD5Loader.cpp | 9 ++-- code/MD5Parser.cpp | 2 +- code/MaterialSystem.cpp | 6 +-- code/Subdivision.cpp | 8 ++-- code/glTFAsset.inl | 2 +- code/glTFExporter.cpp | 2 +- include/assimp/fast_atof.h | 2 +- 28 files changed, 247 insertions(+), 276 deletions(-) diff --git a/code/AMFImporter.cpp b/code/AMFImporter.cpp index d20be6b9f..e5b41b3ad 100644 --- a/code/AMFImporter.cpp +++ b/code/AMFImporter.cpp @@ -230,7 +230,7 @@ casu_cres: if(!skipped_before[sk_idx]) { skipped_before[sk_idx] = true; - LogWarning("Skipping node \"" + nn + "\" in " + pParentNodeName + "."); + ASSIMP_LOG_WARN_F("Skipping node \"", nn, "\" in ", pParentNodeName, "."); } } diff --git a/code/AMFImporter.hpp b/code/AMFImporter.hpp index 060cbf10a..3c60caeab 100644 --- a/code/AMFImporter.hpp +++ b/code/AMFImporter.hpp @@ -358,18 +358,6 @@ private: /************** Functions: LOG set *************/ /***********************************************/ - /// \fn void LogInfo(const std::string& pMessage) - /// Short variant for calling \ref DefaultLogger::get()->info() - void LogInfo(const std::string& pMessage) { DefaultLogger::get()->info(pMessage); } - - /// \fn void LogWarning(const std::string& pMessage) - /// Short variant for calling \ref DefaultLogger::get()->warn() - void LogWarning(const std::string& pMessage) { DefaultLogger::get()->warn(pMessage); } - - /// \fn void LogError(const std::string& pMessage) - /// Short variant for calling \ref DefaultLogger::get()->error() - void LogError(const std::string& pMessage) { DefaultLogger::get()->error(pMessage); } - /***********************************************/ /************** Functions: XML set *************/ /***********************************************/ diff --git a/code/COBLoader.cpp b/code/COBLoader.cpp index ae65f8f93..8571bc492 100644 --- a/code/COBLoader.cpp +++ b/code/COBLoader.cpp @@ -509,22 +509,22 @@ void COBImporter::LogDebug_Ascii(const LineSplitter& splitter, const format& mes // ------------------------------------------------------------------------------------------------ void COBImporter::LogWarn_Ascii(const Formatter::format& message) { - DefaultLogger::get()->warn(std::string("COB: ")+=message); + ASSIMP_LOG_WARN_F( "COB: ", message ); } // ------------------------------------------------------------------------------------------------ void COBImporter::LogError_Ascii(const Formatter::format& message) { - DefaultLogger::get()->error(std::string("COB: ")+=message); + ASSIMP_LOG_ERROR_F( "COB: ", message); } // ------------------------------------------------------------------------------------------------ void COBImporter::LogInfo_Ascii(const Formatter::format& message) { - DefaultLogger::get()->info(std::string("COB: ")+=message); + ASSIMP_LOG_INFO_F("COB: ", message); } // ------------------------------------------------------------------------------------------------ void COBImporter::LogDebug_Ascii(const Formatter::format& message) { - DefaultLogger::get()->debug(std::string("COB: ")+=message); + ASSIMP_LOG_DEBUG_F("COB: ", message); } // ------------------------------------------------------------------------------------------------ diff --git a/code/CSMLoader.cpp b/code/CSMLoader.cpp index 7160740c1..777b6cf1b 100644 --- a/code/CSMLoader.cpp +++ b/code/CSMLoader.cpp @@ -233,7 +233,7 @@ void CSMImporter::InternReadFile( const std::string& pFile, if (TokenMatchI(buffer, "DROPOUT", 7)) { // seems this is invalid marker data; at least the doc says it's possible - DefaultLogger::get()->warn("CSM: Encountered invalid marker data (DROPOUT)"); + ASSIMP_LOG_WARN("CSM: Encountered invalid marker data (DROPOUT)"); } else { aiVectorKey* sub = s->mPositionKeys + s->mNumPositionKeys; diff --git a/code/DXFLoader.cpp b/code/DXFLoader.cpp index 89cc1d654..7d8b6eca2 100644 --- a/code/DXFLoader.cpp +++ b/code/DXFLoader.cpp @@ -200,7 +200,7 @@ void DXFImporter::InternReadFile( const std::string& pFile, // comments else if (reader.Is(999)) { - DefaultLogger::get()->info("DXF Comment: " + reader.Value()); + ASSIMP_LOG_INFO_F("DXF Comment: ", reader.Value()); } // don't read past the official EOF sign @@ -393,7 +393,7 @@ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& bloc // XXX rotation currently ignored - I didn't find an appropriate sample model. if (insert.angle != 0.f) { - DefaultLogger::get()->warn("DXF: BLOCK rotation not currently implemented"); + ASSIMP_LOG_WARN("DXF: BLOCK rotation not currently implemented"); } for (aiVector3D& v : pl_out->positions) { @@ -523,7 +523,7 @@ void DXFImporter::ParseBlock(DXF::LineReader& reader, DXF::FileData& output) // XXX is this a valid case? if (reader.Is(0,"INSERT")) { - DefaultLogger::get()->warn("DXF: INSERT within a BLOCK not currently supported; skipping"); + ASSIMP_LOG_WARN("DXF: INSERT within a BLOCK not currently supported; skipping"); for( ;!reader.End() && !reader.Is(0,"ENDBLK"); ++reader); break; } @@ -678,16 +678,15 @@ void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output) //} if (vguess && line.positions.size() != vguess) { - DefaultLogger::get()->warn((Formatter::format("DXF: unexpected vertex count in polymesh: "), - line.positions.size(),", expected ", vguess - )); + ASSIMP_LOG_WARN_F("DXF: unexpected vertex count in polymesh: ", + line.positions.size(),", expected ", vguess ); } if (line.flags & DXF_POLYLINE_FLAG_POLYFACEMESH ) { if (line.positions.size() < 3 || line.indices.size() < 3) { - DefaultLogger::get()->warn("DXF: not enough vertices for polymesh; ignoring"); - output.blocks.back().lines.pop_back(); - return; + ASSIMP_LOG_WARN("DXF: not enough vertices for polymesh; ignoring"); + output.blocks.back().lines.pop_back(); + return; } // if these numbers are wrong, parsing might have gone wild. @@ -695,13 +694,11 @@ void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output) // to set the 71 and 72 fields, respectively, to valid values. // So just fire a warning. if (iguess && line.counts.size() != iguess) { - DefaultLogger::get()->warn((Formatter::format("DXF: unexpected face count in polymesh: "), - line.counts.size(),", expected ", iguess - )); + ASSIMP_LOG_WARN_F( "DXF: unexpected face count in polymesh: ", line.counts.size(),", expected ", iguess ); } } else if (!line.indices.size() && !line.counts.size()) { - // a polyline - so there are no indices yet. + // a poly-line - so there are no indices yet. size_t guess = line.positions.size() + (line.flags & DXF_POLYLINE_FLAG_CLOSED ? 1 : 0); line.indices.reserve(guess); @@ -743,10 +740,10 @@ void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& li { case 8: // layer to which the vertex belongs to - assume that - // this is always the layer the top-level polyline + // this is always the layer the top-level poly-line // entity resides on as well. if(reader.Value() != line.layer) { - DefaultLogger::get()->warn("DXF: expected vertex to be part of a polyface but the 0x128 flag isn't set"); + ASSIMP_LOG_WARN("DXF: expected vertex to be part of a poly-face but the 0x128 flag isn't set"); } break; @@ -765,7 +762,7 @@ void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& li case 73: case 74: if (cnti == 4) { - DefaultLogger::get()->warn("DXF: more than 4 indices per face not supported; ignoring"); + ASSIMP_LOG_WARN("DXF: more than 4 indices per face not supported; ignoring"); break; } indices[cnti++] = reader.ValueAsUnsignedInt(); @@ -781,7 +778,7 @@ void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& li } if (line.flags & DXF_POLYLINE_FLAG_POLYFACEMESH && !(flags & DXF_VERTEX_FLAG_PART_OF_POLYFACE)) { - DefaultLogger::get()->warn("DXF: expected vertex to be part of a polyface but the 0x128 flag isn't set"); + ASSIMP_LOG_WARN("DXF: expected vertex to be part of a polyface but the 0x128 flag isn't set"); } if (cnti) { @@ -789,7 +786,7 @@ void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& li for (unsigned int i = 0; i < cnti; ++i) { // IMPORTANT NOTE: POLYMESH indices are ONE-BASED if (indices[i] == 0) { - DefaultLogger::get()->warn("DXF: invalid vertex index, indices are one-based."); + ASSIMP_LOG_WARN("DXF: invalid vertex index, indices are one-based."); --line.counts.back(); continue; } @@ -906,7 +903,7 @@ void DXFImporter::Parse3DFace(DXF::LineReader& reader, DXF::FileData& output) // sanity checks to see if we got something meaningful if ((b[1] && !b[0]) || !b[2] || !b[3]) { - DefaultLogger::get()->warn("DXF: unexpected vertex setup in 3DFACE/LINE/FACE entity; ignoring"); + ASSIMP_LOG_WARN("DXF: unexpected vertex setup in 3DFACE/LINE/FACE entity; ignoring"); output.blocks.back().lines.pop_back(); return; } diff --git a/code/Exporter.cpp b/code/Exporter.cpp index b7478c0be..0a8f054b7 100644 --- a/code/Exporter.cpp +++ b/code/Exporter.cpp @@ -363,7 +363,7 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c } if (verbosify || (exp.mEnforcePP & aiProcess_JoinIdenticalVertices)) { - DefaultLogger::get()->debug("export: Scene data not in verbose format, applying MakeVerboseFormat step first"); + ASSIMP_LOG_DEBUG("export: Scene data not in verbose format, applying MakeVerboseFormat step first"); MakeVerboseFormatProcess proc; proc.Execute(scenecopy.get()); diff --git a/code/FBXDocument.cpp b/code/FBXDocument.cpp index a1fbd2cf0..2965a54ff 100644 --- a/code/FBXDocument.cpp +++ b/code/FBXDocument.cpp @@ -214,7 +214,7 @@ const Object* LazyObject::Get(bool dieOnError) // note: the error message is already formatted, so raw logging is ok if(!DefaultLogger::isNullLogger()) { - DefaultLogger::get()->error(ex.what()); + ASSIMP_LOG_ERROR(ex.what()); } return NULL; } diff --git a/code/FBXDocumentUtil.cpp b/code/FBXDocumentUtil.cpp index 775067021..3b1435b5c 100644 --- a/code/FBXDocumentUtil.cpp +++ b/code/FBXDocumentUtil.cpp @@ -79,7 +79,7 @@ void DOMError(const std::string& message, const Element* element /*= NULL*/) void DOMWarning(const std::string& message, const Token& token) { if(DefaultLogger::get()) { - DefaultLogger::get()->warn(Util::AddTokenText("FBX-DOM",message,&token)); + ASSIMP_LOG_WARN(Util::AddTokenText("FBX-DOM",message,&token)); } } diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index c524e3911..4945ec5dc 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -1124,7 +1124,7 @@ void FBXExporter::WriteObjects () err << " has " << m->mNumUVComponents[uvi]; err << " components! Data will be preserved,"; err << " but may be incorrectly interpreted on load."; - DefaultLogger::get()->warn(err.str()); + ASSIMP_LOG_WARN(err.str()); } FBX::Node uv("LayerElementUV", int32_t(uvi)); uv.Begin(outstream, binary, indent); @@ -1449,7 +1449,7 @@ void FBXExporter::WriteObjects () err << "Multilayer textures not supported (for now),"; err << " skipping texture type " << j; err << " of material " << i; - DefaultLogger::get()->warn(err.str()); + ASSIMP_LOG_WARN(err.str()); } // get image path for this (single-image) texture @@ -1484,7 +1484,7 @@ void FBXExporter::WriteObjects () err << "Not sure how to handle texture of type " << j; err << " on material " << i; err << ", skipping..."; - DefaultLogger::get()->warn(err.str()); + ASSIMP_LOG_WARN(err.str()); continue; } const std::string& prop_name = elem2->second; diff --git a/code/IRRLoader.cpp b/code/IRRLoader.cpp index 66d15c5c4..0640b0d66 100644 --- a/code/IRRLoader.cpp +++ b/code/IRRLoader.cpp @@ -131,7 +131,7 @@ void IRRImporter::SetupProperties(const Importer* pImp) // read the output frame rate of all node animation channels fps = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_IRR_ANIM_FPS,100); if (fps < 10.) { - DefaultLogger::get()->error("IRR: Invalid FPS configuration"); + ASSIMP_LOG_ERROR("IRR: Invalid FPS configuration"); fps = 100; } @@ -281,7 +281,7 @@ void IRRImporter::CopyMaterial(std::vector& materials, return; } else if (inmaterials.size() > 1) { - DefaultLogger::get()->info("IRR: Skipping additional materials"); + ASSIMP_LOG_INFO("IRR: Skipping additional materials"); } mesh->mMaterialIndex = (unsigned int)materials.size(); @@ -319,17 +319,18 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vectoranimators.empty()) { return; } - unsigned int total = 0; + unsigned int total( 0 ); for (std::list::iterator it = root->animators.begin();it != root->animators.end(); ++it) { if ((*it).type == Animator::UNKNOWN || (*it).type == Animator::OTHER) { - DefaultLogger::get()->warn("IRR: Skipping unknown or unsupported animator"); + ASSIMP_LOG_WARN("IRR: Skipping unknown or unsupported animator"); continue; } ++total; } - if (!total)return; - else if (1 == total) { - DefaultLogger::get()->warn("IRR: Adding dummy nodes to simulate multiple animators"); + if (!total) { + return; + } else if (1 == total) { + ASSIMP_LOG_WARN("IRR: Adding dummy nodes to simulate multiple animators"); } // NOTE: 1 tick == i millisecond @@ -518,9 +519,9 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vectorwarn("IRR: Spline animators with no points defined"); + ASSIMP_LOG_WARN("IRR: Spline animators with no points defined"); - delete anim;anim = NULL; + delete anim;anim = nullptr; break; } else if (size == 1) { @@ -672,7 +673,7 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene, // graph we're currently building aiScene* scene = batch.GetImport(root->id); if (!scene) { - DefaultLogger::get()->error("IRR: Unable to load external file: " + root->meshPath); + ASSIMP_LOG_ERROR("IRR: Unable to load external file: " + root->meshPath); break; } attach.push_back(AttachmentInfo(scene,rootOut)); @@ -683,7 +684,7 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene, // should be equal. If they are not, we can impossibly // do this ... if (root->materials.size() != (unsigned int)scene->mNumMaterials) { - DefaultLogger::get()->warn("IRR: Failed to match imported materials " + ASSIMP_LOG_WARN("IRR: Failed to match imported materials " "with the materials found in the IRR scene file"); break; @@ -722,7 +723,7 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene, } } if (bdo) { - DefaultLogger::get()->info("IRR: Replacing mesh vertex alpha with common opacity"); + ASSIMP_LOG_INFO("IRR: Replacing mesh vertex alpha with common opacity"); for (unsigned int a = 0; a < mesh->mNumVertices;++a) mesh->mColors[0][a].a = 1.f; @@ -806,7 +807,7 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene, { // A skybox is defined by six materials if (root->materials.size() < 6) { - DefaultLogger::get()->error("IRR: There should be six materials for a skybox"); + ASSIMP_LOG_ERROR("IRR: There should be six materials for a skybox"); break; } @@ -823,7 +824,7 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene, // for IRR skyboxes. We add a 'IRR.SkyBox_' prefix to the node. // ************************************************************* root->name = "IRR.SkyBox_" + root->name; - DefaultLogger::get()->info("IRR: Loading skybox, this will " + ASSIMP_LOG_INFO("IRR: Loading skybox, this will " "require special handling to be displayed correctly"); } break; @@ -831,7 +832,7 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene, case Node::TERRAIN: { // to support terrains, we'd need to have a texture decoder - DefaultLogger::get()->error("IRR: Unsupported node - TERRAIN"); + ASSIMP_LOG_ERROR("IRR: Unsupported node - TERRAIN"); } break; default: @@ -1010,11 +1011,11 @@ void IRRImporter::InternReadFile( const std::string& pFile, } else if (!ASSIMP_stricmp(sz,"billBoard")) { // We don't support billboards, so ignore them - DefaultLogger::get()->error("IRR: Billboards are not supported by Assimp"); + ASSIMP_LOG_ERROR("IRR: Billboards are not supported by Assimp"); nd = new Node(Node::DUMMY); } else { - DefaultLogger::get()->warn("IRR: Found unknown node: " + std::string(sz)); + ASSIMP_LOG_WARN("IRR: Found unknown node: " + std::string(sz)); /* We skip the contents of nodes we don't know. * We parse the transformation and all animators @@ -1041,7 +1042,7 @@ void IRRImporter::InternReadFile( const std::string& pFile, */ if (!curNode) { #if 0 - DefaultLogger::get()->error("IRR: Encountered element, but " + ASSIMP_LOG_ERROR("IRR: Encountered element, but " "there is no node active"); #endif continue; @@ -1269,7 +1270,7 @@ void IRRImporter::InternReadFile( const std::string& pFile, lights.pop_back(); curNode->type = Node::DUMMY; - DefaultLogger::get()->error("Ignoring light of unknown type: " + prop.value); + ASSIMP_LOG_ERROR("Ignoring light of unknown type: " + prop.value); } } else if ((prop.name == "Mesh" && Node::MESH == curNode->type) || @@ -1277,7 +1278,7 @@ void IRRImporter::InternReadFile( const std::string& pFile, { /* This is the file name of the mesh - either * animated or not. We need to make sure we setup - * the correct postprocessing settings here. + * the correct post-processing settings here. */ unsigned int pp = 0; BatchLoader::PropertyMap map; @@ -1299,7 +1300,7 @@ void IRRImporter::InternReadFile( const std::string& pFile, const std::string extension = GetExtension(prop.value); if ("irr" == extension) { - DefaultLogger::get()->error("IRR: Can't load another IRR file recursively"); + ASSIMP_LOG_ERROR("IRR: Can't load another IRR file recursively"); } else { @@ -1323,7 +1324,7 @@ void IRRImporter::InternReadFile( const std::string& pFile, curAnim->type = Animator::FOLLOW_SPLINE; } else { - DefaultLogger::get()->warn("IRR: Ignoring unknown animator: " + ASSIMP_LOG_WARN("IRR: Ignoring unknown animator: " + prop.value); curAnim->type = Animator::UNKNOWN; @@ -1348,7 +1349,7 @@ void IRRImporter::InternReadFile( const std::string& pFile, // back in the node hierarchy if (!curParent) { curParent = root; - DefaultLogger::get()->error("IRR: Too many closing elements"); + ASSIMP_LOG_ERROR("IRR: Too many closing elements"); } else curParent = curParent->parent; } @@ -1369,15 +1370,14 @@ void IRRImporter::InternReadFile( const std::string& pFile, } } - /* Now iterate through all cameras and compute their final (horizontal) FOV - */ + // Now iterate through all cameras and compute their final (horizontal) FOV for (aiCamera *cam : cameras) { - // screen aspect could be missing if (cam->mAspect) { cam->mHorizontalFOV *= cam->mAspect; + } else { + ASSIMP_LOG_WARN("IRR: Camera aspect is not given, can't compute horizontal FOV"); } - else DefaultLogger::get()->warn("IRR: Camera aspect is not given, can't compute horizontal FOV"); } batch.LoadAll(); @@ -1472,7 +1472,7 @@ void IRRImporter::InternReadFile( const std::string& pFile, * models from external files */ if (!pScene->mNumMeshes || !pScene->mNumMaterials) { - DefaultLogger::get()->warn("IRR: No meshes loaded, setting AI_SCENE_FLAGS_INCOMPLETE"); + ASSIMP_LOG_WARN("IRR: No meshes loaded, setting AI_SCENE_FLAGS_INCOMPLETE"); pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; } diff --git a/code/IRRMeshLoader.cpp b/code/IRRMeshLoader.cpp index 5885d69a2..1ed16acd6 100644 --- a/code/IRRMeshLoader.cpp +++ b/code/IRRMeshLoader.cpp @@ -175,7 +175,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile, if (!ASSIMP_stricmp(reader->getNodeName(),"buffer") && (curMat || curMesh)) { // end of previous buffer. A material and a mesh should be there if ( !curMat || !curMesh) { - DefaultLogger::get()->error("IRRMESH: A buffer must contain a mesh and a material"); + ASSIMP_LOG_ERROR("IRRMESH: A buffer must contain a mesh and a material"); releaseMaterial( &curMat ); releaseMesh( &curMesh ); } else { @@ -197,7 +197,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile, if (!ASSIMP_stricmp(reader->getNodeName(),"material")) { if (curMat) { - DefaultLogger::get()->warn("IRRMESH: Only one material description per buffer, please"); + ASSIMP_LOG_WARN("IRRMESH: Only one material description per buffer, please"); releaseMaterial( &curMat ); } curMat = ParseMaterial(curMatFlags); @@ -208,7 +208,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile, if (!num) { // This is possible ... remove the mesh from the list and skip further reading - DefaultLogger::get()->warn("IRRMESH: Found mesh with zero vertices"); + ASSIMP_LOG_WARN("IRRMESH: Found mesh with zero vertices"); releaseMaterial( &curMat ); releaseMesh( &curMesh ); @@ -255,7 +255,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile, } else if (ASSIMP_stricmp("standard", t)) { releaseMaterial( &curMat ); - DefaultLogger::get()->warn("IRRMESH: Unknown vertex format"); + ASSIMP_LOG_WARN("IRRMESH: Unknown vertex format"); } else vertexFormat = 0; textMeaning = 1; @@ -275,7 +275,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile, curMesh->mNumVertices = reader->getAttributeValueAsInt("indexCount"); if (!curMesh->mNumVertices) { // This is possible ... remove the mesh from the list and skip further reading - DefaultLogger::get()->warn("IRRMESH: Found mesh with zero indices"); + ASSIMP_LOG_WARN("IRRMESH: Found mesh with zero indices"); // mesh - away releaseMesh( &curMesh ); @@ -288,7 +288,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile, } if (curMesh->mNumVertices % 3) { - DefaultLogger::get()->warn("IRRMESH: Number if indices isn't divisible by 3"); + ASSIMP_LOG_WARN("IRRMESH: Number if indices isn't divisible by 3"); } curMesh->mNumFaces = curMesh->mNumVertices / 3; @@ -439,7 +439,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile, unsigned int total = 0; while(SkipSpacesAndLineEnd(&sz)) { if (curFace >= faceEnd) { - DefaultLogger::get()->error("IRRMESH: Too many indices"); + ASSIMP_LOG_ERROR("IRRMESH: Too many indices"); break; } if (!curIdx) { @@ -449,7 +449,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile, unsigned int idx = strtoul10(sz,&sz); if (idx >= curVertices.size()) { - DefaultLogger::get()->error("IRRMESH: Index out of range"); + ASSIMP_LOG_ERROR("IRRMESH: Index out of range"); idx = 0; } @@ -492,7 +492,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile, // End of the last buffer. A material and a mesh should be there if (curMat || curMesh) { if ( !curMat || !curMesh) { - DefaultLogger::get()->error("IRRMESH: A buffer must contain a mesh and a material"); + ASSIMP_LOG_ERROR("IRRMESH: A buffer must contain a mesh and a material"); releaseMaterial( &curMat ); releaseMesh( &curMesh ); } diff --git a/code/IRRShared.cpp b/code/IRRShared.cpp index fa90916b3..1e69f1d09 100644 --- a/code/IRRShared.cpp +++ b/code/IRRShared.cpp @@ -179,14 +179,14 @@ void IrrlichtBase::ReadVectorProperty (VectorProperty& out) SkipSpaces(&ptr); if (',' != *ptr) { - DefaultLogger::get()->error("IRR(MESH): Expected comma in vector definition"); + ASSIMP_LOG_ERROR("IRR(MESH): Expected comma in vector definition"); } else SkipSpaces(ptr+1,&ptr); ptr = fast_atoreal_move( ptr,(float&)out.value.y ); SkipSpaces(&ptr); if (',' != *ptr) { - DefaultLogger::get()->error("IRR(MESH): Expected comma in vector definition"); + ASSIMP_LOG_ERROR("IRR(MESH): Expected comma in vector definition"); } else SkipSpaces(ptr+1,&ptr); ptr = fast_atoreal_move( ptr,(float&)out.value.z ); @@ -360,7 +360,7 @@ aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags) matFlags = AI_IRRMESH_MAT_normalmap_ta; } else { - DefaultLogger::get()->warn("IRRMat: Unrecognized material type: " + prop.value); + ASSIMP_LOG_WARN("IRRMat: Unrecognized material type: " + prop.value); } } @@ -391,9 +391,7 @@ aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags) // set the corresponding material flag matFlags |= AI_IRRMESH_EXTRA_2ND_TEXTURE; - } - // or just as second diffuse texture - else if (matFlags & AI_IRRMESH_MAT_solid_2layer) { + } else if (matFlags & AI_IRRMESH_MAT_solid_2layer) {// or just as second diffuse texture ++cnt; s.Set(prop.value); mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(1)); @@ -401,19 +399,15 @@ aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags) // set the corresponding material flag matFlags |= AI_IRRMESH_EXTRA_2ND_TEXTURE; + } else { + ASSIMP_LOG_WARN("IRRmat: Skipping second texture"); } - else DefaultLogger::get()->warn("IRRmat: Skipping second texture"); - } - - else if (prop.name == "Texture3" && cnt == 2) - { + } else if (prop.name == "Texture3" && cnt == 2) { // Irrlicht does not seem to use these channels. ++cnt; s.Set(prop.value); mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(nd+1)); - } - else if (prop.name == "Texture4" && cnt == 3) - { + } else if (prop.name == "Texture4" && cnt == 3) { // Irrlicht does not seem to use these channels. ++cnt; s.Set(prop.value); @@ -499,7 +493,8 @@ aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags) break; } } - DefaultLogger::get()->error("IRRMESH: Unexpected end of file. Material is not complete"); + ASSIMP_LOG_ERROR("IRRMESH: Unexpected end of file. Material is not complete"); + return mat; } diff --git a/code/Importer.cpp b/code/Importer.cpp index f47160c5c..36afc8723 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -504,62 +504,50 @@ const aiScene* Importer::ReadFileFromMemory( const void* pBuffer, // ------------------------------------------------------------------------------------------------ void WriteLogOpening(const std::string& file) { - Logger* l = DefaultLogger::get(); - if (!l) { - return; - } - l->info("Load " + file); + ASSIMP_LOG_INFO_F("Load ", file); // print a full version dump. This is nice because we don't // need to ask the authors of incoming bug reports for // the library version they're using - a log dump is // sufficient. const unsigned int flags = aiGetCompileFlags(); - l->debug(format() - << "Assimp " - << aiGetVersionMajor() - << "." - << aiGetVersionMinor() - << "." - << aiGetVersionRevision() - - << " " + ASSIMP_LOG_DEBUG_F( "Assimp ", aiGetVersionMajor(), ".", aiGetVersionMinor(), ".", aiGetVersionRevision(), " " #if defined(ASSIMP_BUILD_ARCHITECTURE) - << ASSIMP_BUILD_ARCHITECTURE + ,ASSIMP_BUILD_ARCHITECTURE #elif defined(_M_IX86) || defined(__x86_32__) || defined(__i386__) - << "x86" + , "x86" #elif defined(_M_X64) || defined(__x86_64__) - << "amd64" + , "amd64" #elif defined(_M_IA64) || defined(__ia64__) - << "itanium" + , "itanium" #elif defined(__ppc__) || defined(__powerpc__) - << "ppc32" + , "ppc32" #elif defined(__powerpc64__) - << "ppc64" + , "ppc64" #elif defined(__arm__) - << "arm" + , "arm" #else - << "" + , "" #endif - << " " + , " " #if defined(ASSIMP_BUILD_COMPILER) - << ASSIMP_BUILD_COMPILER + , ASSIMP_BUILD_COMPILER #elif defined(_MSC_VER) - << "msvc" + , "msvc" #elif defined(__GNUC__) - << "gcc" + , "gcc" #else - << "" + , "" #endif #ifdef ASSIMP_BUILD_DEBUG - << " debug" + , " debug" #endif - << (flags & ASSIMP_CFLAGS_NOBOOST ? " noboost" : "") - << (flags & ASSIMP_CFLAGS_SHARED ? " shared" : "") - << (flags & ASSIMP_CFLAGS_SINGLETHREADED ? " singlethreaded" : "") + , (flags & ASSIMP_CFLAGS_NOBOOST ? " noboost" : "") + , (flags & ASSIMP_CFLAGS_SHARED ? " shared" : "") + , (flags & ASSIMP_CFLAGS_SINGLETHREADED ? " singlethreaded" : "") ); } diff --git a/code/Importer/IFC/STEPFileReader.cpp b/code/Importer/IFC/STEPFileReader.cpp index 34981d0c5..b1390b9de 100644 --- a/code/Importer/IFC/STEPFileReader.cpp +++ b/code/Importer/IFC/STEPFileReader.cpp @@ -126,7 +126,7 @@ STEP::DB* STEP::ReadFileHeader(std::shared_ptr stream) // XXX need support for multiple schemas? if (list->GetSize() > 1) { - DefaultLogger::get()->warn(AddLineNumber("multiple schemas currently not supported",line)); + ASSIMP_LOG_WARN(AddLineNumber("multiple schemas currently not supported",line)); } const EXPRESS::STRING* string( nullptr ); if (!list->GetSize() || !(string=dynamic_cast( (*list)[0].get() ))) { @@ -192,7 +192,7 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, // LineSplitter already ignores empty lines ai_assert(s.length()); if (s[0] != '#') { - DefaultLogger::get()->warn(AddLineNumber("expected token \'#\'",line)); + ASSIMP_LOG_WARN(AddLineNumber("expected token \'#\'",line)); ++splitter; continue; } @@ -202,14 +202,14 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, // --- const std::string::size_type n0 = s.find_first_of('='); if (n0 == std::string::npos) { - DefaultLogger::get()->warn(AddLineNumber("expected token \'=\'",line)); + ASSIMP_LOG_WARN(AddLineNumber("expected token \'=\'",line)); ++splitter; continue; } const uint64_t id = strtoul10_64(s.substr(1,n0-1).c_str()); if (!id) { - DefaultLogger::get()->warn(AddLineNumber("expected positive, numeric entity id",line)); + ASSIMP_LOG_WARN(AddLineNumber("expected positive, numeric entity id",line)); ++splitter; continue; } @@ -236,7 +236,7 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, } if(!ok) { - DefaultLogger::get()->warn(AddLineNumber("expected token \'(\'",line)); + ASSIMP_LOG_WARN(AddLineNumber("expected token \'(\'",line)); continue; } } @@ -263,13 +263,13 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, } } if(!ok) { - DefaultLogger::get()->warn(AddLineNumber("expected token \')\'",line)); + ASSIMP_LOG_WARN(AddLineNumber("expected token \')\'",line)); continue; } } if (map.find(id) != map.end()) { - DefaultLogger::get()->warn(AddLineNumber((Formatter::format(),"an object with the id #",id," already exists"),line)); + ASSIMP_LOG_WARN(AddLineNumber((Formatter::format(),"an object with the id #",id," already exists"),line)); } std::string::size_type ns = n0; @@ -292,7 +292,7 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, } if (!splitter) { - DefaultLogger::get()->warn("STEP: ignoring unexpected EOF"); + ASSIMP_LOG_WARN("STEP: ignoring unexpected EOF"); } if ( !DefaultLogger::isNullLogger()){ @@ -392,7 +392,7 @@ std::shared_ptr EXPRESS::DataType::Parse(const char*& i std::string stemp = std::string(start, static_cast(cur - start)); if(!StringToUTF8(stemp)) { // TODO: route this to a correct logger with line numbers etc., better error messages - DefaultLogger::get()->error("an error occurred reading escape sequences in ASCII text"); + ASSIMP_LOG_ERROR("an error occurred reading escape sequences in ASCII text"); } return std::make_shared(stemp); diff --git a/code/LWOBLoader.cpp b/code/LWOBLoader.cpp index 45e149914..fabf99cad 100644 --- a/code/LWOBLoader.cpp +++ b/code/LWOBLoader.cpp @@ -74,7 +74,7 @@ void LWOImporter::LoadLWOBFile() case AI_LWO_PNTS: { if (!mCurLayer->mTempPoints.empty()) - DefaultLogger::get()->warn("LWO: PNTS chunk encountered twice"); + ASSIMP_LOG_WARN("LWO: PNTS chunk encountered twice"); else LoadLWOPoints(head.length); break; } @@ -83,7 +83,7 @@ void LWOImporter::LoadLWOBFile() { if (!mCurLayer->mFaces.empty()) - DefaultLogger::get()->warn("LWO: POLS chunk encountered twice"); + ASSIMP_LOG_WARN("LWO: POLS chunk encountered twice"); else LoadLWOBPolygons(head.length); break; } @@ -91,7 +91,7 @@ void LWOImporter::LoadLWOBFile() case AI_LWO_SRFS: { if (!mTags->empty()) - DefaultLogger::get()->warn("LWO: SRFS chunk encountered twice"); + ASSIMP_LOG_WARN("LWO: SRFS chunk encountered twice"); else LoadLWOTags(head.length); break; } @@ -183,20 +183,20 @@ void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it, break; } face.mIndices = new unsigned int[face.mNumIndices]; - for (unsigned int i = 0; i < face.mNumIndices;++i) - { + for (unsigned int i = 0; i < face.mNumIndices;++i) { unsigned int & mi = face.mIndices[i]; uint16_t index; ::memcpy(&index, cursor++, 2); mi = index; if (mi > mCurLayer->mTempPoints.size()) { - DefaultLogger::get()->warn("LWOB: face index is out of range"); + ASSIMP_LOG_WARN("LWOB: face index is out of range"); mi = (unsigned int)mCurLayer->mTempPoints.size()-1; } } + } else { + ASSIMP_LOG_WARN("LWOB: Face has 0 indices"); } - else DefaultLogger::get()->warn("LWOB: Face has 0 indices"); int16_t surface; ::memcpy(&surface, cursor++, 2); if (surface < 0) @@ -242,7 +242,7 @@ LWO::Texture* LWOImporter::SetupNewTextureLWOB(LWO::TextureList& list,unsigned i else { // procedural or gradient, not supported - DefaultLogger::get()->error("LWOB: Unsupported legacy texture: " + type); + ASSIMP_LOG_ERROR_F("LWOB: Unsupported legacy texture: ", type); } return tex; @@ -273,7 +273,7 @@ void LWOImporter::LoadLWOBSurface(unsigned int size) * how much storage is actually left and work with this value from now on. */ if (mFileBuffer + head.length > end) { - DefaultLogger::get()->error("LWOB: Invalid surface chunk length. Trying to continue."); + ASSIMP_LOG_ERROR("LWOB: Invalid surface chunk length. Trying to continue."); head.length = (uint16_t) (end - mFileBuffer); } @@ -381,8 +381,9 @@ void LWOImporter::LoadLWOBSurface(unsigned int size) { if (pTex) { GetS0(pTex->mFileName,head.length); + } else { + ASSIMP_LOG_WARN("LWOB: Unexpected TIMG chunk"); } - else DefaultLogger::get()->warn("LWOB: Unexpected TIMG chunk"); break; } // texture strength @@ -391,8 +392,9 @@ void LWOImporter::LoadLWOBSurface(unsigned int size) AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TVAL,1); if (pTex) { pTex->mStrength = (float)GetU1()/ 255.f; + } else { + ASSIMP_LOG_ERROR("LWOB: Unexpected TVAL chunk"); } - else DefaultLogger::get()->warn("LWOB: Unexpected TVAL chunk"); break; } // texture flags @@ -400,8 +402,7 @@ void LWOImporter::LoadLWOBSurface(unsigned int size) { AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TFLG,2); - if (pTex) - { + if (nullptr != pTex) { const uint16_t s = GetU2(); if (s & 1) pTex->majorAxis = LWO::Texture::AXIS_X; @@ -410,10 +411,13 @@ void LWOImporter::LoadLWOBSurface(unsigned int size) else if (s & 4) pTex->majorAxis = LWO::Texture::AXIS_Z; - if (s & 16) - DefaultLogger::get()->warn("LWOB: Ignoring \'negate\' flag on texture"); + if (s & 16) { + ASSIMP_LOG_WARN("LWOB: Ignoring \'negate\' flag on texture"); + } + } + else { + ASSIMP_LOG_WARN("LWOB: Unexpected TFLG chunk"); } - else DefaultLogger::get()->warn("LWOB: Unexpected TFLG chunk"); break; } } diff --git a/code/LWOLoader.cpp b/code/LWOLoader.cpp index e908ea178..d654935b4 100644 --- a/code/LWOLoader.cpp +++ b/code/LWOLoader.cpp @@ -188,7 +188,7 @@ void LWOImporter::InternReadFile( const std::string& pFile, // old lightwave file format (prior to v6) if (AI_LWO_FOURCC_LWOB == fileType) { - DefaultLogger::get()->info("LWO file format: LWOB (<= LightWave 5.5)"); + ASSIMP_LOG_INFO("LWO file format: LWOB (<= LightWave 5.5)"); mIsLWO2 = false; mIsLXOB = false; @@ -197,12 +197,12 @@ void LWOImporter::InternReadFile( const std::string& pFile, // New lightwave format else if (AI_LWO_FOURCC_LWO2 == fileType) { mIsLXOB = false; - DefaultLogger::get()->info("LWO file format: LWO2 (>= LightWave 6)"); + ASSIMP_LOG_INFO("LWO file format: LWO2 (>= LightWave 6)"); } // MODO file format else if (AI_LWO_FOURCC_LXOB == fileType) { mIsLXOB = true; - DefaultLogger::get()->info("LWO file format: LXOB (Modo)"); + ASSIMP_LOG_INFO("LWO file format: LXOB (Modo)"); } // we don't know this format else @@ -271,7 +271,7 @@ void LWOImporter::InternReadFile( const std::string& pFile, unsigned int idx = (*it).surfaceIndex; if (idx >= mTags->size()) { - DefaultLogger::get()->warn("LWO: Invalid face surface index"); + ASSIMP_LOG_WARN("LWO: Invalid face surface index"); idx = UINT_MAX; } if(UINT_MAX == idx || UINT_MAX == (idx = _mMapping[idx])) { @@ -423,7 +423,9 @@ void LWOImporter::InternReadFile( const std::string& pFile, // So we use a separate implementation. ComputeNormals(mesh,smoothingGroups,_mSurfaces[i]); } - else DefaultLogger::get()->debug("LWO2: No need to compute normals, they're already there"); + else { + ASSIMP_LOG_DEBUG("LWO2: No need to compute normals, they're already there"); + } ++p; } } @@ -686,13 +688,13 @@ void LWOImporter::ResolveClips() if (Clip::REF == clip.type) { if (clip.clipRef >= mClips.size()) { - DefaultLogger::get()->error("LWO2: Clip referrer index is out of range"); + ASSIMP_LOG_ERROR("LWO2: Clip referrer index is out of range"); clip.clipRef = 0; } Clip& dest = mClips[clip.clipRef]; if (Clip::REF == dest.type) { - DefaultLogger::get()->error("LWO2: Clip references another clip reference"); + ASSIMP_LOG_ERROR("LWO2: Clip references another clip reference"); clip.type = Clip::UNSUPPORTED; } @@ -711,7 +713,7 @@ void LWOImporter::AdjustTexturePath(std::string& out) if (!mIsLWO2 && ::strstr(out.c_str(), "(sequence)")) { // remove the (sequence) and append 000 - DefaultLogger::get()->info("LWOB: Sequence of animated texture found. It will be ignored"); + ASSIMP_LOG_INFO("LWOB: Sequence of animated texture found. It will be ignored"); out = out.substr(0,out.length()-10) + "000"; } @@ -786,10 +788,10 @@ void LWOImporter::LoadLWO2Polygons(unsigned int length) { // read unsupported stuff too (although we won't process it) case AI_LWO_MBAL: - DefaultLogger::get()->warn("LWO2: Encountered unsupported primitive chunk (METABALL)"); + ASSIMP_LOG_WARN("LWO2: Encountered unsupported primitive chunk (METABALL)"); break; case AI_LWO_CURV: - DefaultLogger::get()->warn("LWO2: Encountered unsupported primitive chunk (SPLINE)");; + ASSIMP_LOG_WARN("LWO2: Encountered unsupported primitive chunk (SPLINE)");; break; // These are ok with no restrictions @@ -801,7 +803,7 @@ void LWOImporter::LoadLWO2Polygons(unsigned int length) default: // hm!? wtf is this? ok ... - DefaultLogger::get()->error("LWO2: Ignoring unknown polygon type."); + ASSIMP_LOG_ERROR("LWO2: Ignoring unknown polygon type."); break; } @@ -864,7 +866,7 @@ void LWOImporter::CopyFaceIndicesLWO2(FaceList::iterator& it, face.mIndices[i] = ReadVSizedIntLWO2((uint8_t*&)cursor) + mCurLayer->mPointIDXOfs; if(face.mIndices[i] > mCurLayer->mTempPoints.size()) { - DefaultLogger::get()->warn("LWO2: Failure evaluating face record, index is out of range"); + ASSIMP_LOG_WARN("LWO2: Failure evaluating face record, index is out of range"); face.mIndices[i] = (unsigned int)mCurLayer->mTempPoints.size()-1; } } @@ -891,7 +893,7 @@ void LWOImporter::LoadLWO2PolygonTags(unsigned int length) unsigned int j = GetU2(); if (i >= mCurLayer->mFaces.size()) { - DefaultLogger::get()->warn("LWO2: face index in PTAG is out of range"); + ASSIMP_LOG_WARN("LWO2: face index in PTAG is out of range"); continue; } @@ -914,7 +916,7 @@ VMapEntry* FindEntry(std::vector< T >& list,const std::string& name, bool perPol for (auto & elem : list) { if (elem.name == name) { if (!perPoly) { - DefaultLogger::get()->warn("LWO2: Found two VMAP sections with equal names"); + ASSIMP_LOG_WARN("LWO2: Found two VMAP sections with equal names"); } return &elem; } @@ -999,7 +1001,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) { case AI_LWO_TXUV: if (dims != 2) { - DefaultLogger::get()->warn("LWO2: Skipping UV channel \'" + ASSIMP_LOG_WARN("LWO2: Skipping UV channel \'" + name + "\' with !2 components"); return; } @@ -1008,7 +1010,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) case AI_LWO_WGHT: case AI_LWO_MNVW: if (dims != 1) { - DefaultLogger::get()->warn("LWO2: Skipping Weight Channel \'" + ASSIMP_LOG_WARN("LWO2: Skipping Weight Channel \'" + name + "\' with !1 components"); return; } @@ -1018,7 +1020,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) case AI_LWO_RGB: case AI_LWO_RGBA: if (dims != 3 && dims != 4) { - DefaultLogger::get()->warn("LWO2: Skipping Color Map \'" + ASSIMP_LOG_WARN("LWO2: Skipping Color Map \'" + name + "\' with a dimension > 4 or < 3"); return; } @@ -1033,7 +1035,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) if (name != "vert_normals" || dims != 3 || mCurLayer->mNormals.name.length()) return; - DefaultLogger::get()->info("Processing non-standard extension: MODO VMAP.NORM.vert_normals"); + ASSIMP_LOG_INFO("Processing non-standard extension: MODO VMAP.NORM.vert_normals"); mCurLayer->mNormals.name = name; base = & mCurLayer->mNormals; @@ -1048,7 +1050,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) if (name == "APS.Level") { // XXX handle this (seems to be subdivision-related). } - DefaultLogger::get()->warn("LWO2: Skipping unknown VMAP/VMAD channel \'" + name + "\'"); + ASSIMP_LOG_WARN_F("LWO2: Skipping unknown VMAP/VMAD channel \'", name, "\'"); return; }; base->Allocate((unsigned int)mCurLayer->mTempPoints.size()); @@ -1068,7 +1070,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) unsigned int idx = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mPointIDXOfs; if (idx >= numPoints) { - DefaultLogger::get()->warn("LWO2: Failure evaluating VMAP/VMAD entry \'" + name + "\', vertex index is out of range"); + ASSIMP_LOG_WARN_F("LWO2: Failure evaluating VMAP/VMAD entry \'", name, "\', vertex index is out of range"); mFileBuffer += base->dims<<2u; continue; } @@ -1119,7 +1121,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) CreateNewEntry(mCurLayer->mNormals, srcIdx ); } if (!had) { - DefaultLogger::get()->warn("LWO2: Failure evaluating VMAD entry \'" + name + "\', vertex index wasn't found in that polygon"); + ASSIMP_LOG_WARN_F("LWO2: Failure evaluating VMAD entry \'", name, "\', vertex index wasn't found in that polygon"); ai_assert(had); } } @@ -1180,11 +1182,11 @@ void LWOImporter::LoadLWO2Clip(unsigned int length) break; case AI_LWO_STCC: - DefaultLogger::get()->warn("LWO2: Color shifted images are not supported"); + ASSIMP_LOG_WARN("LWO2: Color shifted images are not supported"); break; case AI_LWO_ANIM: - DefaultLogger::get()->warn("LWO2: Animated textures are not supported"); + ASSIMP_LOG_WARN("LWO2: Animated textures are not supported"); break; case AI_LWO_XREF: @@ -1201,7 +1203,7 @@ void LWOImporter::LoadLWO2Clip(unsigned int length) break; default: - DefaultLogger::get()->warn("LWO2: Encountered unknown CLIP subchunk"); + ASSIMP_LOG_WARN("LWO2: Encountered unknown CLIP sub-chunk"); } } @@ -1282,7 +1284,7 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length) { AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPAN,4); if (envelope.keys.size()<2) - DefaultLogger::get()->warn("LWO2: Unexpected SPAN chunk"); + ASSIMP_LOG_WARN("LWO2: Unexpected SPAN chunk"); else { LWO::Key& key = envelope.keys.back(); switch (GetU4()) @@ -1300,7 +1302,7 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length) case AI_LWO_BEZ2: key.inter = LWO::IT_BEZ2;break; default: - DefaultLogger::get()->warn("LWO2: Unknown interval interpolation mode"); + ASSIMP_LOG_WARN("LWO2: Unknown interval interpolation mode"); }; // todo ... read params @@ -1309,7 +1311,8 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length) } default: - DefaultLogger::get()->warn("LWO2: Encountered unknown ENVL subchunk"); + ASSIMP_LOG_WARN("LWO2: Encountered unknown ENVL subchunk"); + break; } // regardless how much we did actually read, go to the next chunk mFileBuffer = next; @@ -1408,7 +1411,7 @@ void LWOImporter::LoadLWO2File() case AI_LWO_VMAD: if (mCurLayer->mFaces.empty()) { - DefaultLogger::get()->warn("LWO2: Unexpected VMAD chunk"); + ASSIMP_LOG_WARN("LWO2: Unexpected VMAD chunk"); break; } // --- intentionally no break here @@ -1418,7 +1421,7 @@ void LWOImporter::LoadLWO2File() break; if (mCurLayer->mTempPoints.empty()) - DefaultLogger::get()->warn("LWO2: Unexpected VMAP chunk"); + ASSIMP_LOG_WARN("LWO2: Unexpected VMAP chunk"); else LoadLWO2VertexMap(head.length,head.type == AI_LWO_VMAD); break; } @@ -1448,7 +1451,7 @@ void LWOImporter::LoadLWO2File() case AI_LWO_TAGS: { if (!mTags->empty()) - DefaultLogger::get()->warn("LWO2: SRFS chunk encountered twice"); + ASSIMP_LOG_WARN("LWO2: SRFS chunk encountered twice"); else LoadLWOTags(head.length); break; } diff --git a/code/LWOLoader.h b/code/LWOLoader.h index fa646648d..4d42eb2d2 100644 --- a/code/LWOLoader.h +++ b/code/LWOLoader.h @@ -473,7 +473,7 @@ inline void LWOImporter::GetS0(std::string& out,unsigned int max) { if (++iCursor > max) { - DefaultLogger::get()->warn("LWO: Invalid file, string is is too long"); + ASSIMP_LOG_WARN("LWO: Invalid file, string is is too long"); break; } ++mFileBuffer; diff --git a/code/LWOMaterial.cpp b/code/LWOMaterial.cpp index 383d3acb7..f4f43ced6 100644 --- a/code/LWOMaterial.cpp +++ b/code/LWOMaterial.cpp @@ -74,7 +74,7 @@ inline aiTextureMapMode GetMapMode(LWO::Texture::Wrap in) return aiTextureMapMode_Mirror; case LWO::Texture::RESET: - DefaultLogger::get()->warn("LWO2: Unsupported texture map mode: RESET"); + ASSIMP_LOG_WARN("LWO2: Unsupported texture map mode: RESET"); // fall though here case LWO::Texture::EDGE: @@ -117,7 +117,7 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex mapping = aiTextureMapping_BOX; break; case LWO::Texture::FrontProjection: - DefaultLogger::get()->error("LWO2: Unsupported texture mapping: FrontProjection"); + ASSIMP_LOG_ERROR("LWO2: Unsupported texture mapping: FrontProjection"); mapping = aiTextureMapping_OTHER; break; case LWO::Texture::UV: @@ -181,7 +181,7 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex } if (candidate == end) { - DefaultLogger::get()->error("LWO2: Clip index is out of bounds"); + ASSIMP_LOG_ERROR("LWO2: Clip index is out of bounds"); temp = 0; // fixme: apparently some LWO files shipping with Doom3 don't @@ -194,7 +194,7 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex } else { if (Clip::UNSUPPORTED == (*candidate).type) { - DefaultLogger::get()->error("LWO2: Clip type is not supported"); + ASSIMP_LOG_ERROR("LWO2: Clip type is not supported"); continue; } AdjustTexturePath((*candidate).path); @@ -212,7 +212,7 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex { std::string ss = texture.mFileName; if (!ss.length()) { - DefaultLogger::get()->error("LWOB: Empty file name"); + ASSIMP_LOG_WARN("LWOB: Empty file name"); continue; } AdjustTexturePath(ss); @@ -246,7 +246,7 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex default: temp = (unsigned int)aiTextureOp_Multiply; - DefaultLogger::get()->warn("LWO2: Unsupported texture blend mode: alpha or displacement"); + ASSIMP_LOG_WARN("LWO2: Unsupported texture blend mode: alpha or displacement"); } // Setup texture operation @@ -347,20 +347,20 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat) // the surface and search for a name which we know ... for (const auto &shader : surf.mShaders) { if (shader.functionName == "LW_SuperCelShader" || shader.functionName == "AH_CelShader") { - DefaultLogger::get()->info("LWO2: Mapping LW_SuperCelShader/AH_CelShader to aiShadingMode_Toon"); + ASSIMP_LOG_INFO("LWO2: Mapping LW_SuperCelShader/AH_CelShader to aiShadingMode_Toon"); m = aiShadingMode_Toon; break; } else if (shader.functionName == "LW_RealFresnel" || shader.functionName == "LW_FastFresnel") { - DefaultLogger::get()->info("LWO2: Mapping LW_RealFresnel/LW_FastFresnel to aiShadingMode_Fresnel"); + ASSIMP_LOG_INFO("LWO2: Mapping LW_RealFresnel/LW_FastFresnel to aiShadingMode_Fresnel"); m = aiShadingMode_Fresnel; break; } else { - DefaultLogger::get()->warn("LWO2: Unknown surface shader: " + shader.functionName); + ASSIMP_LOG_WARN_F("LWO2: Unknown surface shader: ", shader.functionName); } } if (surf.mMaximumSmoothAngle <= 0.0) @@ -398,7 +398,7 @@ char LWOImporter::FindUVChannels(LWO::TextureList& list, } else { // channel mismatch. need to duplicate the material. - DefaultLogger::get()->warn("LWO: Channel mismatch, would need to duplicate surface [design bug]"); + ASSIMP_LOG_WARN("LWO: Channel mismatch, would need to duplicate surface [design bug]"); // TODO } @@ -429,7 +429,7 @@ void LWOImporter::FindUVChannels(LWO::Surface& surf, if (extra >= AI_MAX_NUMBER_OF_TEXTURECOORDS) { - DefaultLogger::get()->error("LWO: Maximum number of UV channels for " + ASSIMP_LOG_ERROR("LWO: Maximum number of UV channels for " "this mesh reached. Skipping channel \'" + uv.name + "\'"); } @@ -502,7 +502,7 @@ void LWOImporter::FindVCChannels(const LWO::Surface& surf, LWO::SortedRep& sorte if (vc.abAssigned[idx] && ((aiColor4D*)&vc.rawData[0])[idx] != aiColor4D(0.0,0.0,0.0,1.0)) { if (next >= AI_MAX_NUMBER_OF_COLOR_SETS) { - DefaultLogger::get()->error("LWO: Maximum number of vertex color channels for " + ASSIMP_LOG_ERROR("LWO: Maximum number of vertex color channels for " "this mesh reached. Skipping channel \'" + vc.name + "\'"); } @@ -567,7 +567,7 @@ void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex ) void LWOImporter::LoadLWO2Procedural(unsigned int /*size*/, LWO::Texture& tex ) { // --- not supported at the moment - DefaultLogger::get()->error("LWO2: Found procedural texture, this is not supported"); + ASSIMP_LOG_ERROR("LWO2: Found procedural texture, this is not supported"); tex.bCanUse = false; } @@ -575,7 +575,7 @@ void LWOImporter::LoadLWO2Procedural(unsigned int /*size*/, LWO::Texture& tex ) void LWOImporter::LoadLWO2Gradient(unsigned int /*size*/, LWO::Texture& tex ) { // --- not supported at the moment - DefaultLogger::get()->error("LWO2: Found gradient texture, this is not supported"); + ASSIMP_LOG_ERROR("LWO2: Found gradient texture, this is not supported"); tex.bCanUse = false; } @@ -590,7 +590,7 @@ void LWOImporter::LoadLWO2TextureHeader(unsigned int size, LWO::Texture& tex ) // we could crash later if this is an empty string ... if (!tex.ordinal.length()) { - DefaultLogger::get()->error("LWO2: Ill-formed SURF.BLOK ordinal string"); + ASSIMP_LOG_ERROR("LWO2: Ill-formed SURF.BLOK ordinal string"); tex.ordinal = "\x00"; } while (true) @@ -662,7 +662,7 @@ void LWOImporter::LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader* head, unsi case AI_LWO_REFL: listRef = &surf.mReflectionTextures;break; default: - DefaultLogger::get()->warn("LWO2: Encountered unknown texture type"); + ASSIMP_LOG_WARN("LWO2: Encountered unknown texture type"); return; } @@ -691,7 +691,7 @@ void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* /*head*/, u // we could crash later if this is an empty string ... if (!shader.ordinal.length()) { - DefaultLogger::get()->error("LWO2: Ill-formed SURF.BLOK ordinal string"); + ASSIMP_LOG_ERROR("LWO2: Ill-formed SURF.BLOK ordinal string"); shader.ordinal = "\x00"; } @@ -750,7 +750,7 @@ void LWOImporter::LoadLWO2Surface(unsigned int size) } } if (derived.size()) - DefaultLogger::get()->warn("LWO2: Unable to find source surface: " + derived); + ASSIMP_LOG_WARN("LWO2: Unable to find source surface: " + derived); } while (true) @@ -886,7 +886,7 @@ void LWOImporter::LoadLWO2Surface(unsigned int size) break; default: - DefaultLogger::get()->warn("LWO2: Found an unsupported surface BLOK"); + ASSIMP_LOG_WARN("LWO2: Found an unsupported surface BLOK"); }; break; diff --git a/code/LWSLoader.cpp b/code/LWSLoader.cpp index baff6ab06..4313359d8 100644 --- a/code/LWSLoader.cpp +++ b/code/LWSLoader.cpp @@ -200,7 +200,7 @@ void LWSImporter::SetupProperties(const Importer* pImp) void LWSImporter::ReadEnvelope(const LWS::Element& dad, LWO::Envelope& fill ) { if (dad.children.empty()) { - DefaultLogger::get()->error("LWS: Envelope descriptions must not be empty"); + ASSIMP_LOG_ERROR("LWS: Envelope descriptions must not be empty"); return; } @@ -248,7 +248,7 @@ void LWSImporter::ReadEnvelope(const LWS::Element& dad, LWO::Envelope& fill ) num = 4; break; default: - DefaultLogger::get()->error("LWS: Unknown span type"); + ASSIMP_LOG_ERROR("LWS: Unknown span type"); } for (unsigned int i = 0; i < num;++i) { SkipSpaces(&c); @@ -305,7 +305,7 @@ void LWSImporter::ReadEnvelope_Old( return; unexpected_end: - DefaultLogger::get()->error("LWS: Encountered unexpected end of file while parsing object motion"); + ASSIMP_LOG_ERROR("LWS: Encountered unexpected end of file while parsing object motion"); } // ------------------------------------------------------------------------------------------------ @@ -352,7 +352,7 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vectorerror("LWS: Failed to read external file " + src.path); + ASSIMP_LOG_ERROR("LWS: Failed to read external file " + src.path); } else { if (obj->mRootNode->mNumChildren == 1) { @@ -551,7 +551,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, // get file format version and print to log ++it; unsigned int version = strtoul10((*it).tokens[0].c_str()); - DefaultLogger::get()->info("LWS file format version is " + (*it).tokens[0]); + ASSIMP_LOG_INFO("LWS file format version is " + (*it).tokens[0]); first = 0.; last = 60.; fps = 25.; /* seems to be a good default frame rate */ @@ -656,7 +656,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, d.number = cur_object++; nodes.push_back(d); } - else DefaultLogger::get()->error("LWS: Unexpected keyword: \'Channel\'"); + ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'Channel\'"); } // important: index of channel @@ -673,7 +673,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, // 'Envelope': a single animation channel else if ((*it).tokens[0] == "Envelope") { if (nodes.empty() || nodes.back().channels.empty()) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'Envelope\'"); + ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'Envelope\'"); else { ReadEnvelope((*it),nodes.back().channels.back()); } @@ -684,7 +684,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, (*it).tokens[0] == "LightMotion")) { if (nodes.empty()) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'Motion\'"); + DASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'Motion\'"); else { ReadEnvelope_Old(it,root.children.end(),nodes.back(),version); } @@ -692,7 +692,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, // 'Pre/PostBehavior': pre/post animation behaviour for LWSC 2 else if (version == 2 && (*it).tokens[0] == "Pre/PostBehavior") { if (nodes.empty()) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'Pre/PostBehavior'"); + ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'Pre/PostBehavior'"); else { for (std::list::iterator it = nodes.back().channels.begin(); it != nodes.back().channels.end(); ++it) { // two ints per envelope @@ -705,14 +705,14 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, // 'ParentItem': specifies the parent of the current element else if ((*it).tokens[0] == "ParentItem") { if (nodes.empty()) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'ParentItem\'"); + ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'ParentItem\'"); else nodes.back().parent = strtoul16(c,&c); } // 'ParentObject': deprecated one for older formats else if (version < 3 && (*it).tokens[0] == "ParentObject") { if (nodes.empty()) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'ParentObject\'"); + ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'ParentObject\'"); else { nodes.back().parent = strtoul10(c,&c) | (1u << 28u); @@ -736,7 +736,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, // 'CameraName': set name of currently active camera else if ((*it).tokens[0] == "CameraName") { if (nodes.empty() || nodes.back().type != LWS::NodeDesc::CAMERA) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'CameraName\'"); + ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'CameraName\'"); else nodes.back().name = c; } @@ -758,14 +758,14 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, // 'LightName': set name of currently active light else if ((*it).tokens[0] == "LightName") { if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightName\'"); + ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightName\'"); else nodes.back().name = c; } // 'LightIntensity': set intensity of currently active light else if ((*it).tokens[0] == "LightIntensity" || (*it).tokens[0] == "LgtIntensity" ) { if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightIntensity\'"); + ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightIntensity\'"); else fast_atoreal_move(c, nodes.back().lightIntensity ); @@ -781,7 +781,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, // 'LightFalloffType': set falloff type of currently active light else if ((*it).tokens[0] == "LightFalloffType") { if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightFalloffType\'"); + ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightFalloffType\'"); else nodes.back().lightFalloffType = strtoul10(c); @@ -789,7 +789,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, // 'LightConeAngle': set cone angle of currently active light else if ((*it).tokens[0] == "LightConeAngle") { if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightConeAngle\'"); + ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightConeAngle\'"); else nodes.back().lightConeAngle = fast_atof(c); @@ -797,7 +797,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, // 'LightEdgeAngle': set area where we're smoothing from min to max intensity else if ((*it).tokens[0] == "LightEdgeAngle") { if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightEdgeAngle\'"); + ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightEdgeAngle\'"); else nodes.back().lightEdgeAngle = fast_atof(c); @@ -805,7 +805,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, // 'LightColor': set color of currently active light else if ((*it).tokens[0] == "LightColor") { if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightColor\'"); + ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightColor\'"); else { c = fast_atoreal_move(c, (float&) nodes.back().lightColor.r ); @@ -819,7 +819,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, // 'PivotPosition': position of local transformation origin else if ((*it).tokens[0] == "PivotPosition" || (*it).tokens[0] == "PivotPoint") { if (nodes.empty()) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'PivotPosition\'"); + ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'PivotPosition\'"); else { c = fast_atoreal_move(c, (float&) nodes.back().pivotPos.x ); SkipSpaces(&c); @@ -840,7 +840,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, if (dit != it && *it == (*dit).parent) { if ((*dit).parent_resolved) { // fixme: it's still possible to produce an overflow due to cross references .. - DefaultLogger::get()->error("LWS: Found cross reference in scenegraph"); + ASSIMP_LOG_ERROR("LWS: Found cross reference in scene-graph"); continue; } diff --git a/code/MD2Loader.cpp b/code/MD2Loader.cpp index 8f5b1c045..cfd5458e7 100644 --- a/code/MD2Loader.cpp +++ b/code/MD2Loader.cpp @@ -83,7 +83,7 @@ void MD2::LookupNormalIndex(uint8_t iNormalIndex,aiVector3D& vOut) { // make sure the normal index has a valid value if (iNormalIndex >= ARRAYSIZE(g_avNormals)) { - DefaultLogger::get()->warn("Index overflow in Quake II normal vector list"); + ASSIMP_LOG_WARN("Index overflow in Quake II normal vector list"); iNormalIndex = ARRAYSIZE(g_avNormals) - 1; } vOut = *((const aiVector3D*)(&g_avNormals[iNormalIndex])); @@ -161,7 +161,7 @@ void MD2Importer::ValidateHeader( ) // check file format version if (m_pcHeader->version != 8) - DefaultLogger::get()->warn( "Unsupported md2 file version. Continuing happily ..."); + ASSIMP_LOG_WARN( "Unsupported md2 file version. Continuing happily ..."); // check some values whether they are valid if (0 == m_pcHeader->numFrames) @@ -203,11 +203,11 @@ void MD2Importer::ValidateHeader( ) } if (m_pcHeader->numSkins > AI_MD2_MAX_SKINS) - DefaultLogger::get()->warn("The model contains more skins than Quake 2 supports"); + ASSIMP_LOG_WARN("The model contains more skins than Quake 2 supports"); if ( m_pcHeader->numFrames > AI_MD2_MAX_FRAMES) - DefaultLogger::get()->warn("The model contains more frames than Quake 2 supports"); + ASSIMP_LOG_WARN("The model contains more frames than Quake 2 supports"); if (m_pcHeader->numVertices > AI_MD2_MAX_VERTS) - DefaultLogger::get()->warn("The model contains more vertices than Quake 2 supports"); + ASSIMP_LOG_WARN("The model contains more vertices than Quake 2 supports"); if (m_pcHeader->numFrames <= configFrameID ) throw DeadlyImportError("The requested frame is not existing the file"); @@ -352,7 +352,7 @@ void MD2Importer::InternReadFile( const std::string& pFile, pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0)); } else{ - DefaultLogger::get()->warn("Texture file name has zero length. It will be skipped."); + ASSIMP_LOG_WARN("Texture file name has zero length. It will be skipped."); } } else { @@ -390,11 +390,11 @@ void MD2Importer::InternReadFile( const std::string& pFile, // check whether the skin width or height are zero (this would // cause a division through zero) if (!m_pcHeader->skinWidth) { - DefaultLogger::get()->error("MD2: No valid skin width given"); + ASSIMP_LOG_ERROR("MD2: No valid skin width given"); } else fDivisorU = (float)m_pcHeader->skinWidth; if (!m_pcHeader->skinHeight){ - DefaultLogger::get()->error("MD2: No valid skin height given"); + ASSIMP_LOG_ERROR("MD2: No valid skin height given"); } else fDivisorV = (float)m_pcHeader->skinHeight; } @@ -412,7 +412,7 @@ void MD2Importer::InternReadFile( const std::string& pFile, // validate vertex indices unsigned int iIndex = (unsigned int)pcTriangles[i].vertexIndices[c]; if (iIndex >= m_pcHeader->numVertices) { - DefaultLogger::get()->error("MD2: Vertex index is outside the allowed range"); + ASSIMP_LOG_ERROR("MD2: Vertex index is outside the allowed range"); iIndex = m_pcHeader->numVertices-1; } @@ -440,7 +440,7 @@ void MD2Importer::InternReadFile( const std::string& pFile, // validate texture coordinates iIndex = pcTriangles[i].textureIndices[c]; if (iIndex >= m_pcHeader->numTexCoords) { - DefaultLogger::get()->error("MD2: UV index is outside the allowed range"); + ASSIMP_LOG_ERROR("MD2: UV index is outside the allowed range"); iIndex = m_pcHeader->numTexCoords-1; } diff --git a/code/MD3Loader.cpp b/code/MD3Loader.cpp index 7b71ee42f..4e0b24acb 100644 --- a/code/MD3Loader.cpp +++ b/code/MD3Loader.cpp @@ -101,7 +101,7 @@ Q3Shader::BlendFunc StringToBlendFunc(const std::string& m) if (m == "GL_ONE_MINUS_DST_COLOR") { return Q3Shader::BLEND_GL_ONE_MINUS_DST_COLOR; } - DefaultLogger::get()->error("Q3Shader: Unknown blend function: " + m); + ASSIMP_LOG_ERROR("Q3Shader: Unknown blend function: " + m); return Q3Shader::BLEND_NONE; } @@ -113,7 +113,7 @@ bool Q3Shader::LoadShader(ShaderData& fill, const std::string& pFile,IOSystem* i if (!file.get()) return false; // if we can't access the file, don't worry and return - DefaultLogger::get()->info("Loading Quake3 shader file " + pFile); + ASSIMP_LOG_INFO_F("Loading Quake3 shader file ", pFile); // read file in memory const size_t s = file->FileSize(); @@ -136,7 +136,7 @@ bool Q3Shader::LoadShader(ShaderData& fill, const std::string& pFile,IOSystem* i // append to last section, if any if (!curData) { - DefaultLogger::get()->error("Q3Shader: Unexpected shader section token \'{\'"); + ASSIMP_LOG_ERROR("Q3Shader: Unexpected shader section token \'{\'"); return true; // still no failure, the file is there } @@ -206,19 +206,16 @@ bool Q3Shader::LoadShader(ShaderData& fill, const std::string& pFile,IOSystem* i SkipSpaces(&buff); if (!ASSIMP_strincmp(buff,"back",4)) { curData->cull = Q3Shader::CULL_CCW; - } - else if (!ASSIMP_strincmp(buff,"front",5)) { + } else if (!ASSIMP_strincmp(buff,"front",5)) { curData->cull = Q3Shader::CULL_CW; - } - else if (!ASSIMP_strincmp(buff,"none",4) || !ASSIMP_strincmp(buff,"disable",7)) { + } else if (!ASSIMP_strincmp(buff,"none",4) || !ASSIMP_strincmp(buff,"disable",7)) { curData->cull = Q3Shader::CULL_NONE; + } else { + ASSIMP_LOG_ERROR("Q3Shader: Unrecognized cull mode"); } - else DefaultLogger::get()->error("Q3Shader: Unrecognized cull mode"); } } - } - - else { + } else { // add new section fill.blocks.push_back(Q3Shader::ShaderDataBlock()); curData = &fill.blocks.back(); @@ -238,7 +235,7 @@ bool Q3Shader::LoadSkin(SkinData& fill, const std::string& pFile,IOSystem* io) if (!file.get()) return false; // if we can't access the file, don't worry and return - DefaultLogger::get()->info("Loading Quake3 skin file " + pFile); + ASSIMP_LOG_INFO("Loading Quake3 skin file " + pFile); // read file in memory const size_t s = file->FileSize(); @@ -397,7 +394,7 @@ void MD3Importer::ValidateHeaderOffsets() // Check file format version if (pcHeader->VERSION > 15) - DefaultLogger::get()->warn( "Unsupported MD3 file version. Continuing happily ..."); + ASSIMP_LOG_WARN( "Unsupported MD3 file version. Continuing happily ..."); // Check some offset values whether they are valid if (!pcHeader->NUM_SURFACES) @@ -438,25 +435,24 @@ void MD3Importer::ValidateSurfaceHeaderOffsets(const MD3::Surface* pcSurf) // Check whether all requirements for Q3 files are met. We don't // care, but probably someone does. if (pcSurf->NUM_TRIANGLES > AI_MD3_MAX_TRIANGLES) { - DefaultLogger::get()->warn("MD3: Quake III triangle limit exceeded"); + ASSIMP_LOG_WARN("MD3: Quake III triangle limit exceeded"); } if (pcSurf->NUM_SHADER > AI_MD3_MAX_SHADERS) { - DefaultLogger::get()->warn("MD3: Quake III shader limit exceeded"); + ASSIMP_LOG_WARN("MD3: Quake III shader limit exceeded"); } if (pcSurf->NUM_VERTICES > AI_MD3_MAX_VERTS) { - DefaultLogger::get()->warn("MD3: Quake III vertex limit exceeded"); + ASSIMP_LOG_WARN("MD3: Quake III vertex limit exceeded"); } if (pcSurf->NUM_FRAMES > AI_MD3_MAX_FRAMES) { - DefaultLogger::get()->warn("MD3: Quake III frame limit exceeded"); + ASSIMP_LOG_WARN("MD3: Quake III frame limit exceeded"); } } // ------------------------------------------------------------------------------------------------ -const aiImporterDesc* MD3Importer::GetInfo () const -{ +const aiImporterDesc* MD3Importer::GetInfo () const { return &desc; } @@ -579,7 +575,7 @@ bool MD3Importer::ReadMultipartFile() aiNode* tag_torso, *tag_head; std::vector attach; - DefaultLogger::get()->info("Multi part MD3 player model: lower, upper and head parts are joined"); + ASSIMP_LOG_INFO("Multi part MD3 player model: lower, upper and head parts are joined"); // ensure we won't try to load ourselves recursively BatchLoader::PropertyMap props; @@ -600,21 +596,21 @@ bool MD3Importer::ReadMultipartFile() // ... and get them. We need all of them. scene_lower = batch.GetImport(_lower); if (!scene_lower) { - DefaultLogger::get()->error("M3D: Failed to read multi part model, lower.md3 fails to load"); + ASSIMP_LOG_ERROR("M3D: Failed to read multi part model, lower.md3 fails to load"); failure = "lower"; goto error_cleanup; } scene_upper = batch.GetImport(_upper); if (!scene_upper) { - DefaultLogger::get()->error("M3D: Failed to read multi part model, upper.md3 fails to load"); + ASSIMP_LOG_ERROR("M3D: Failed to read multi part model, upper.md3 fails to load"); failure = "upper"; goto error_cleanup; } scene_head = batch.GetImport(_head); if (!scene_head) { - DefaultLogger::get()->error("M3D: Failed to read multi part model, head.md3 fails to load"); + ASSIMP_LOG_ERROR("M3D: Failed to read multi part model, head.md3 fails to load"); failure = "head"; goto error_cleanup; } @@ -628,7 +624,7 @@ bool MD3Importer::ReadMultipartFile() // tag_torso tag_torso = scene_lower->mRootNode->FindNode("tag_torso"); if (!tag_torso) { - DefaultLogger::get()->error("M3D: Failed to find attachment tag for multi part model: tag_torso expected"); + ASSIMP_LOG_ERROR("M3D: Failed to find attachment tag for multi part model: tag_torso expected"); goto error_cleanup; } scene_upper->mRootNode->mName.Set("upper"); @@ -637,7 +633,7 @@ bool MD3Importer::ReadMultipartFile() // tag_head tag_head = scene_upper->mRootNode->FindNode("tag_head"); if (!tag_head) { - DefaultLogger::get()->error("M3D: Failed to find attachment tag for multi part model: tag_head expected"); + ASSIMP_LOG_ERROR( "M3D: Failed to find attachment tag for multi part model: tag_head expected"); goto error_cleanup; } scene_head->mRootNode->mName.Set("head"); @@ -919,9 +915,10 @@ void MD3Importer::InternReadFile( const std::string& pFile, if (dit != shaders.blocks.end()) { // Hurra, wir haben einen. Tolle Sache. shader = &*dit; - DefaultLogger::get()->info("Found shader record for " +without_ext ); + ASSIMP_LOG_INFO("Found shader record for " +without_ext ); + } else { + ASSIMP_LOG_WARN("Unable to find shader record for " + without_ext); } - else DefaultLogger::get()->warn("Unable to find shader record for " +without_ext ); } aiMaterial* pcHelper = new aiMaterial(); @@ -950,7 +947,7 @@ void MD3Importer::InternReadFile( const std::string& pFile, szString.Set(convertedPath); } else { - DefaultLogger::get()->warn("Texture file name has zero length. Using default name"); + ASSIMP_LOG_WARN("Texture file name has zero length. Using default name"); szString.Set("dummy_texture.bmp"); } pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0)); @@ -1040,7 +1037,7 @@ void MD3Importer::InternReadFile( const std::string& pFile, if (!DefaultLogger::isNullLogger()) { for (std::list< Q3Shader::SkinData::TextureEntry>::const_iterator it = skins.textures.begin();it != skins.textures.end(); ++it) { if (!(*it).resolved) { - DefaultLogger::get()->error("MD3: Failed to match skin " + (*it).first + " to surface " + (*it).second); + ASSIMP_LOG_ERROR("MD3: Failed to match skin ", (*it).first, " to surface ", (*it).second); } } } diff --git a/code/MD5Loader.cpp b/code/MD5Loader.cpp index d5aea6a47..fc9c97cf3 100644 --- a/code/MD5Loader.cpp +++ b/code/MD5Loader.cpp @@ -359,7 +359,7 @@ void MD5Importer::LoadMD5MeshFile () // Check whether we can read from the file if( file.get() == NULL || !file->FileSize()) { - DefaultLogger::get()->warn("Failed to access MD5MESH file: " + pFile); + ASSIMP_LOG_WARN("Failed to access MD5MESH file: " + pFile); return; } bHadMD5Mesh = true; @@ -482,7 +482,7 @@ void MD5Importer::LoadMD5MeshFile () for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights;++w) fSum += meshSrc.mWeights[w].mWeight; if (!fSum) { - DefaultLogger::get()->error("MD5MESH: The sum of all vertex bone weights is 0"); + ASSIMP_LOG_ERROR("MD5MESH: The sum of all vertex bone weights is 0"); continue; } @@ -574,7 +574,7 @@ void MD5Importer::LoadMD5AnimFile () // Check whether we can read from the file if( !file.get() || !file->FileSize()) { - DefaultLogger::get()->warn("Failed to read MD5ANIM file: " + pFile); + ASSIMP_LOG_WARN("Failed to read MD5ANIM file: " + pFile); return; } LoadFileIntoMemory(file.get()); @@ -588,8 +588,7 @@ void MD5Importer::LoadMD5AnimFile () // generate and fill the output animation if (animParser.mAnimatedBones.empty() || animParser.mFrames.empty() || animParser.mBaseFrames.size() != animParser.mAnimatedBones.size()) { - - DefaultLogger::get()->error("MD5ANIM: No frames or animated bones loaded"); + ASSIMP_LOG_ERROR("MD5ANIM: No frames or animated bones loaded"); } else { bHadMD5Anim = true; diff --git a/code/MD5Parser.cpp b/code/MD5Parser.cpp index d927d998a..7fa4db1ba 100644 --- a/code/MD5Parser.cpp +++ b/code/MD5Parser.cpp @@ -107,7 +107,7 @@ MD5Parser::MD5Parser(char* _buffer, unsigned int _fileSize ) { char szBuffer[1024]; ::sprintf(szBuffer,"[MD5] Line %u: %s",line,warn); - DefaultLogger::get()->warn(szBuffer); + ASSIMP_LOG_WARN(szBuffer); } // ------------------------------------------------------------------------------------------------ diff --git a/code/MaterialSystem.cpp b/code/MaterialSystem.cpp index e7e8a077d..97892658f 100644 --- a/code/MaterialSystem.cpp +++ b/code/MaterialSystem.cpp @@ -160,7 +160,7 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat, break; } if ( !IsSpace(*cur) ) { - DefaultLogger::get()->error("Material property" + std::string(pKey) + + ASSIMP_LOG_ERROR("Material property" + std::string(pKey) + " is a string; failed to parse a float array out of it."); return AI_FAILURE; } @@ -233,7 +233,7 @@ aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat, break; } if(!IsSpace(*cur)) { - DefaultLogger::get()->error("Material property" + std::string(pKey) + + ASSIMP_LOG_ERROR("Material property" + std::string(pKey) + " is a string; failed to parse an integer array out of it."); return AI_FAILURE; } @@ -305,7 +305,7 @@ aiReturn aiGetMaterialString(const aiMaterial* pMat, } else { // TODO - implement lexical cast as well - DefaultLogger::get()->error("Material property" + std::string(pKey) + + ASSIMP_LOG_ERROR("Material property" + std::string(pKey) + " was found, but is no string" ); return AI_FAILURE; } diff --git a/code/Subdivision.cpp b/code/Subdivision.cpp index f2e480db1..ced560764 100644 --- a/code/Subdivision.cpp +++ b/code/Subdivision.cpp @@ -177,7 +177,7 @@ void CatmullClarkSubdivider::Subdivide ( aiMesh* i = smesh[s]; // FIX - mPrimitiveTypes might not yet be initialized if (i->mPrimitiveTypes && (i->mPrimitiveTypes & (aiPrimitiveType_LINE|aiPrimitiveType_POINT))==i->mPrimitiveTypes) { - DefaultLogger::get()->debug("Catmull-Clark Subdivider: Skipping pure line/point mesh"); + ASSIMP_LOG_DEBUG("Catmull-Clark Subdivider: Skipping pure line/point mesh"); if (discard_input) { out[s] = i; @@ -198,12 +198,12 @@ void CatmullClarkSubdivider::Subdivide ( // checking any ranges. ai_assert(inmeshes.size()==outmeshes.size()&&inmeshes.size()==maptbl.size()); if (inmeshes.empty()) { - DefaultLogger::get()->warn("Catmull-Clark Subdivider: Pure point/line scene, I can't do anything"); + ASSIMP_LOG_WARN("Catmull-Clark Subdivider: Pure point/line scene, I can't do anything"); return; } InternSubdivide(&inmeshes.front(),inmeshes.size(),&outmeshes.front(),num); for (unsigned int i = 0; i < maptbl.size(); ++i) { - ai_assert(outmeshes[i]); + ai_assert(nullptr != outmeshes[i]); out[maptbl[i]] = outmeshes[i]; } @@ -563,7 +563,7 @@ void CatmullClarkSubdivider::InternSubdivide ( // this invariant *must* hold if the vertex-to-face adjacency table is valid ai_assert(haveit); if ( !haveit ) { - DefaultLogger::get()->warn( "OBJ: no name for material library specified." ); + ASSIMP_LOG_WARN( "OBJ: no name for material library specified." ); } } diff --git a/code/glTFAsset.inl b/code/glTFAsset.inl index bd43b19f2..267cbd4a3 100644 --- a/code/glTFAsset.inl +++ b/code/glTFAsset.inl @@ -869,7 +869,7 @@ inline void Mesh::Read(Value& pJSON_Object, Asset& pAsset_Root) if(comp_data == nullptr) throw DeadlyImportError("GLTF: \"Open3DGC-compression\" must has \"compressedData\"."); - DefaultLogger::get()->info("GLTF: Decompressing Open3DGC data."); + ASSIMP_LOG_INFO("GLTF: Decompressing Open3DGC data."); /************** Read data from JSON-document **************/ #define MESH_READ_COMPRESSEDDATA_MEMBER(pFieldName, pOut) \ diff --git a/code/glTFExporter.cpp b/code/glTFExporter.cpp index ccbbd7fa2..7dfe5b3ff 100644 --- a/code/glTFExporter.cpp +++ b/code/glTFExporter.cpp @@ -568,7 +568,7 @@ void glTFExporter::ExportMeshes() else msg = "mesh must has vertices and faces."; - DefaultLogger::get()->warn("GLTF: can not use Open3DGC-compression: " + msg); + ASSIMP_LOG_WARN_F("GLTF: can not use Open3DGC-compression: ", msg); comp_allow = false; } diff --git a/include/assimp/fast_atof.h b/include/assimp/fast_atof.h index e66f1b37d..735cfe2da 100644 --- a/include/assimp/fast_atof.h +++ b/include/assimp/fast_atof.h @@ -199,7 +199,7 @@ uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_ino // numeric overflow, we rely on you if ( new_value < value ) { - DefaultLogger::get()->warn( std::string( "Converting the string \"" ) + in + "\" into a value resulted in overflow." ); + ASSIMP_LOG_WARN_F( "Converting the string \"", in, "\" into a value resulted in overflow." ); return 0; } From ce6a5e5d561c96ef8db0a5098576d51c7a340633 Mon Sep 17 00:00:00 2001 From: Sergio Acereda Date: Mon, 23 Apr 2018 11:33:48 +0200 Subject: [PATCH 159/278] ImproveCacheLocality crashes if non triangular faces --- code/ImproveCacheLocality.cpp | 13 ++++++++----- code/VertexTriangleAdjacency.cpp | 24 ++++++++++++------------ 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/code/ImproveCacheLocality.cpp b/code/ImproveCacheLocality.cpp index cc6e9db46..ac079ade5 100644 --- a/code/ImproveCacheLocality.cpp +++ b/code/ImproveCacheLocality.cpp @@ -276,8 +276,9 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh // so iterate through all vertices of the current triangle const aiFace* pcFace = &pMesh->mFaces[ fidx ]; - for (unsigned int* p = pcFace->mIndices, *p2 = pcFace->mIndices+3;p != p2;++p) { - const unsigned int dp = *p; + unsigned nind = pcFace->mNumIndices; + for (unsigned ind = 0; ind < nind; ind++) { + unsigned dp = pcFace->mIndices[ind]; // the current vertex won't have any free triangles after this step if (ivdx != (int)dp) { @@ -375,9 +376,11 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh // sort the output index buffer back to the input array piCSIter = piIBOutput; for (aiFace* pcFace = pMesh->mFaces; pcFace != pcEnd;++pcFace) { - pcFace->mIndices[0] = *piCSIter++; - pcFace->mIndices[1] = *piCSIter++; - pcFace->mIndices[2] = *piCSIter++; + unsigned nind = pcFace->mNumIndices; + unsigned * ind = pcFace->mIndices; + if (nind > 0) ind[0] = *piCSIter++; + if (nind > 1) ind[1] = *piCSIter++; + if (nind > 2) ind[2] = *piCSIter++; } // delete temporary storage diff --git a/code/VertexTriangleAdjacency.cpp b/code/VertexTriangleAdjacency.cpp index 5886ca372..b41fd029d 100644 --- a/code/VertexTriangleAdjacency.cpp +++ b/code/VertexTriangleAdjacency.cpp @@ -88,10 +88,13 @@ VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces, *piEnd++ = 0u; // first pass: compute the number of faces referencing each vertex - for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) { - pi[pcFace->mIndices[0]]++; - pi[pcFace->mIndices[1]]++; - pi[pcFace->mIndices[2]]++; + for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) + { + unsigned nind = pcFace->mNumIndices; + unsigned * ind = pcFace->mIndices; + if (nind > 0) pi[ind[0]]++; + if (nind > 1) pi[ind[1]]++; + if (nind > 2) pi[ind[2]]++; } // second pass: compute the final offset table @@ -109,15 +112,12 @@ VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces, this->mAdjacencyTable = new unsigned int[iSum]; iSum = 0; for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace,++iSum) { + unsigned nind = pcFace->mNumIndices; + unsigned * ind = pcFace->mIndices; - unsigned int idx = pcFace->mIndices[0]; - mAdjacencyTable[pi[idx]++] = iSum; - - idx = pcFace->mIndices[1]; - mAdjacencyTable[pi[idx]++] = iSum; - - idx = pcFace->mIndices[2]; - mAdjacencyTable[pi[idx]++] = iSum; + if (nind > 0) mAdjacencyTable[pi[ind[0]]++] = iSum; + if (nind > 1) mAdjacencyTable[pi[ind[1]]++] = iSum; + if (nind > 2) mAdjacencyTable[pi[ind[2]]++] = iSum; } // fourth pass: undo the offset computations made during the third pass // We could do this in a separate buffer, but this would be TIMES slower. From 43dedb6e0980f779ce61240e17d1df064cac65f7 Mon Sep 17 00:00:00 2001 From: Sergio Acereda Date: Mon, 23 Apr 2018 12:23:12 +0200 Subject: [PATCH 160/278] unit test: missing mNumIndices --- test/unit/utVertexTriangleAdjacency.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/unit/utVertexTriangleAdjacency.cpp b/test/unit/utVertexTriangleAdjacency.cpp index 046ce25f0..dc109f519 100644 --- a/test/unit/utVertexTriangleAdjacency.cpp +++ b/test/unit/utVertexTriangleAdjacency.cpp @@ -101,8 +101,11 @@ TEST_F(VTAdjacencyTest, smallDataSet) mesh.mFaces = new aiFace[3]; mesh.mFaces[0].mIndices = new unsigned int[3]; + mesh.mFaces[0].mNumIndices = 3; mesh.mFaces[1].mIndices = new unsigned int[3]; + mesh.mFaces[1].mNumIndices = 3; mesh.mFaces[2].mIndices = new unsigned int[3]; + mesh.mFaces[2].mNumIndices = 3; mesh.mFaces[0].mIndices[0] = 1; mesh.mFaces[0].mIndices[1] = 3; From 2d6782cc9fcf31257225265ae4153dc163ca61dd Mon Sep 17 00:00:00 2001 From: Jeroen Bollen Date: Tue, 24 Apr 2018 16:44:22 +0200 Subject: [PATCH 161/278] Changed 'souces' to 'sources'. There was a typo in the `CMakeLists.txt` where if zlib was not found, it would say "Compiling from souces" instead of "Compiling from sources". Added a 'r' to fix the typo. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index add601d1b..cb407c4b1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -311,7 +311,7 @@ IF ( NOT ASSIMP_BUILD_ZLIB ) ENDIF( NOT ASSIMP_BUILD_ZLIB ) IF( NOT ZLIB_FOUND ) - MESSAGE(STATUS "compiling zlib from souces") + MESSAGE(STATUS "compiling zlib from sources") INCLUDE(CheckIncludeFile) INCLUDE(CheckTypeSize) INCLUDE(CheckFunctionExists) From 0fdb79871f8e87abd79301986bc025d5005ef852 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven!=20Ragnar=C3=B6k?= Date: Tue, 24 Apr 2018 10:12:30 -0700 Subject: [PATCH 162/278] Use CMAKE_INSTALL_PREFIX as ASSIMP_ROOT_DIR. Since the ASSIMP_LIB_INSTALL_DIR where this CMake config file is installed to may contain multiple nested directories, we should not use it to back-calculate the location of the ASSIMP_ROOT_DIR unless we can take the directory depth into account. Instead use the CMAKE_INSTALL_PREFIX as the ASSIMP_ROOT_DIR at configure-time. This approach is more flexible with respect to install directories but it means that assimp files are not relocatable after installation and I don't think it works if a DESTDIR option is provided when running `make install` after cmake configuration. --- assimp-config.cmake.in | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/assimp-config.cmake.in b/assimp-config.cmake.in index 5031c8f8d..1710cac5d 100644 --- a/assimp-config.cmake.in +++ b/assimp-config.cmake.in @@ -10,10 +10,7 @@ # ASSIMP_LIBRARY_DIRS - link directories # ASSIMP_LIBRARIES - libraries to link plugins with # ASSIMP_Boost_VERSION - the boost version assimp was compiled with -get_filename_component(_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) -get_filename_component(_PREFIX "${_PREFIX}" PATH) -get_filename_component(_PREFIX "${_PREFIX}" PATH) -get_filename_component(ASSIMP_ROOT_DIR "${_PREFIX}" PATH) +get_filename_component(ASSIMP_ROOT_DIR "@CMAKE_INSTALL_PREFIX@" REALPATH) if( MSVC ) # in order to prevent DLL hell, each of the DLLs have to be suffixed with the major version and msvc prefix From a8077baed5da03e273a2c316f77852fe4071cd40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Fricoteaux?= Date: Wed, 25 Apr 2018 11:37:56 +0200 Subject: [PATCH 163/278] Add vertex color support to glTF2 export --- code/glTF2Exporter.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index e146327ea..0c2677fb2 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -732,6 +732,14 @@ void glTF2Exporter::ExportMeshes() } } + /*************** Vertex colors ****************/ + for (unsigned int indexColorChannel = 0; indexColorChannel < aim->GetNumColorChannels(); ++indexColorChannel) + { + Ref c = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mColors[indexColorChannel], AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT, false); + if (c) + p.attributes.color.push_back(c); + } + /*************** Vertices indices ****************/ if (aim->mNumFaces > 0) { std::vector indices; From 6b4caa0f12ead97d29c4eea401fda1ccfa5e2917 Mon Sep 17 00:00:00 2001 From: wuxiaoqian Date: Thu, 26 Apr 2018 10:56:56 +0800 Subject: [PATCH 164/278] fix export gltf2, The JOINTS_0 componentType is incorrect --- code/glTF2Asset.h | 1 + code/glTF2Asset.inl | 23 +++++++++++++++++++++++ code/glTF2Exporter.cpp | 20 ++++++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index cece307d9..dd27398a4 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -601,6 +601,7 @@ namespace glTF2 /// \param [in] pReplace_Count - count of bytes in new data. /// \return true - if successfully replaced, false if input arguments is out of range. bool ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count); + bool ReplaceData_joint(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count); size_t AppendData(uint8_t* data, size_t length); void Grow(size_t amount); diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 549df747e..e51f234c1 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -481,6 +481,29 @@ uint8_t* new_data; return true; } +inline bool Buffer::ReplaceData_joint(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count) +{ +const size_t new_data_size = byteLength + pReplace_Count - pBufferData_Count; + +uint8_t* new_data; + + if((pBufferData_Count == 0) || (pReplace_Count == 0) || (pReplace_Data == nullptr)) return false; + + new_data = new uint8_t[new_data_size]; + // Copy data which place before replacing part. + memcpy(new_data, mData.get(), pBufferData_Offset); + // Copy new data. + memcpy(&new_data[pBufferData_Offset], pReplace_Data, pReplace_Count); + // Copy data which place after replacing part. + memcpy(&new_data[pBufferData_Offset + pReplace_Count], &mData.get()[pBufferData_Offset + pBufferData_Count] + , new_data_size - (pBufferData_Offset + pReplace_Count) + ); + // Apply new data + mData.reset(new_data, std::default_delete()); + byteLength = new_data_size; + + return true; +} inline size_t Buffer::AppendData(uint8_t* data, size_t length) { diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index c1a803c1f..3f4fe9cd0 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -623,6 +623,26 @@ void ExportSkin(Asset& mAsset, const aiMesh* aimesh, Ref& meshRef, Refprimitives.back(); Ref vertexJointAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, vertexJointData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT); if ( vertexJointAccessor ) { + unsigned int offset = vertexJointAccessor->bufferView->byteOffset; + unsigned int bytesLen = vertexJointAccessor->bufferView->byteLength; + unsigned int s_bytesPerComp= ComponentTypeSize(ComponentType_UNSIGNED_SHORT); + unsigned int bytesPerComp = ComponentTypeSize(vertexJointAccessor->componentType); + unsigned int s_bytesLen = bytesLen * s_bytesPerComp / bytesPerComp; + Ref buf = vertexJointAccessor->bufferView->buffer; + uint8_t* arrys = new uint8_t[s_bytesLen]; + unsigned int i = 0; + for ( unsigned int j = 0; j <= bytesLen; j += bytesPerComp ){ + size_t len_p = offset + j; + float f_value = *(float *)&buf->GetPointer()[len_p]; + unsigned short c = static_cast(f_value); + uint8_t* data = new uint8_t[s_bytesPerComp]; + data = (uint8_t*)&c; + memcpy(&arrys[i*s_bytesPerComp], data, s_bytesPerComp); + ++i; + } + buf->ReplaceData_joint(offset, bytesLen, arrys, s_bytesLen); + vertexJointAccessor->componentType = ComponentType_UNSIGNED_SHORT; + p.attributes.joint.push_back( vertexJointAccessor ); } From 30c20eb5fcbd0d54cc44eb5ee25710dce73e7673 Mon Sep 17 00:00:00 2001 From: kimkulling Date: Thu, 26 Apr 2018 14:10:18 +0200 Subject: [PATCH 165/278] INtroduce new log macros. --- code/Assimp.cpp | 2 +- code/BlenderDNA.cpp | 2 +- code/BlenderDNA.inl | 2 +- code/BlenderModifier.h | 2 +- code/COBLoader.cpp | 92 +++++++------------------------ code/COBLoader.h | 22 +------- code/CalcTangentsProcess.cpp | 12 ++-- code/ComputeUVMappingProcess.cpp | 12 ++-- code/ConvertToLHProcess.cpp | 18 +++--- code/DeboneProcess.cpp | 8 +-- code/EmbedTexturesProcess.cpp | 8 +-- code/FBXDocumentUtil.cpp | 2 +- code/FindDegenerates.cpp | 13 ++--- code/FindInstancesProcess.cpp | 10 ++-- code/FindInvalidDataProcess.cpp | 12 ++-- code/FixNormalsStep.cpp | 38 +++++++------ code/GenFaceNormalsProcess.cpp | 17 +++--- code/GenVertexNormalsProcess.cpp | 17 +++--- code/IRRMeshLoader.cpp | 2 +- code/Importer.cpp | 43 ++++++++------- code/ImproveCacheLocality.cpp | 20 ++----- code/JoinVerticesProcess.cpp | 28 ++++------ code/LWOLoader.cpp | 16 ++++-- code/LWSLoader.cpp | 4 +- code/LimitBoneWeightsProcess.cpp | 16 +++--- code/MD5Parser.cpp | 4 +- code/MDCLoader.cpp | 10 ++-- code/MDLLoader.cpp | 6 +- code/MDLMaterialLoader.cpp | 13 +++-- code/MS3DLoader.cpp | 5 +- code/MakeVerboseFormat.cpp | 11 ++-- code/NDOLoader.cpp | 8 +-- code/NFFLoader.cpp | 33 +++++------ code/OFFLoader.cpp | 8 +-- code/ObjFileImporter.cpp | 4 +- code/ObjFileMtlImporter.cpp | 2 +- code/ObjFileParser.cpp | 16 +++--- code/OgreBinarySerializer.cpp | 44 +++++++-------- code/OgreMaterial.cpp | 33 ++++++----- code/OgreXmlSerializer.cpp | 66 ++++++++++------------ code/OpenGEXImporter.cpp | 7 +-- code/OptimizeGraph.cpp | 10 ++-- code/OptimizeMeshes.cpp | 10 ++-- code/PlyParser.cpp | 34 ++++++------ code/PretransformVertices.cpp | 26 +++------ code/ProcessHelper.cpp | 2 +- code/ProcessHelper.h | 2 +- code/Q3DLoader.cpp | 4 +- code/RawLoader.cpp | 2 +- code/RemoveRedundantMaterials.cpp | 12 ++-- code/RemoveVCProcess.cpp | 11 ++-- code/SIBImporter.cpp | 4 +- code/SMDLoader.cpp | 8 +-- code/STEPFile.h | 4 +- code/STLLoader.cpp | 12 ++-- code/SortByPTypeProcess.cpp | 8 +-- code/SplitLargeMeshes.cpp | 19 ++++--- code/Subdivision.cpp | 7 +-- code/TerragenLoader.cpp | 2 +- code/TextureTransform.cpp | 32 +++++------ code/TriangulateProcess.cpp | 11 ++-- code/ValidateDataStructure.cpp | 4 +- code/XFileImporter.cpp | 2 +- code/XFileParser.cpp | 20 +++---- include/assimp/LogAux.h | 10 ++-- 65 files changed, 413 insertions(+), 531 deletions(-) diff --git a/code/Assimp.cpp b/code/Assimp.cpp index 44e3ed563..b682d257b 100644 --- a/code/Assimp.cpp +++ b/code/Assimp.cpp @@ -146,7 +146,7 @@ private: // ------------------------------------------------------------------------------------------------ void ReportSceneNotFoundError() { - DefaultLogger::get()->error("Unable to find the Assimp::Importer for this aiScene. " + ASSIMP_LOG_ERROR("Unable to find the Assimp::Importer for this aiScene. " "The C-API does not accept scenes produced by the C++ API and vice versa"); ai_assert(false); diff --git a/code/BlenderDNA.cpp b/code/BlenderDNA.cpp index 0bca902c6..afcbb34e3 100644 --- a/code/BlenderDNA.cpp +++ b/code/BlenderDNA.cpp @@ -210,7 +210,7 @@ void DNAParser::Parse () s.size = offset; } - ASSIMP_LOG_DEBUG( "BlenderDNA: Got ", dna.structures.size()," structures with totally ",fields," fields"); + ASSIMP_LOG_DEBUG_F( "BlenderDNA: Got ", dna.structures.size()," structures with totally ",fields," fields"); #ifdef ASSIMP_BUILD_BLENDER_DEBUG dna.DumpToFile(); diff --git a/code/BlenderDNA.inl b/code/BlenderDNA.inl index 1f345b631..e43d15d38 100644 --- a/code/BlenderDNA.inl +++ b/code/BlenderDNA.inl @@ -468,7 +468,7 @@ template <> bool Structure :: ResolvePointer(std::shar // this might happen if DNA::RegisterConverters hasn't been called so far // or if the target type is not contained in `our` DNA. out.reset(); - ASSIMP_LOG_WARN( "Failed to find a converter for the `",s.name,"` structure" ); + ASSIMP_LOG_WARN_F( "Failed to find a converter for the `",s.name,"` structure" ); return false; } diff --git a/code/BlenderModifier.h b/code/BlenderModifier.h index 1b0976b1e..b8797691b 100644 --- a/code/BlenderModifier.h +++ b/code/BlenderModifier.h @@ -86,7 +86,7 @@ public: const Scene& /*in*/, const Object& /*orig_object*/ ) { - ASSIMP_LOG_INFO_F("This modifier is not supported, skipping: "),orig_modifier.dna_type); + ASSIMP_LOG_INFO_F("This modifier is not supported, skipping: ",orig_modifier.dna_type ); return; } }; diff --git a/code/COBLoader.cpp b/code/COBLoader.cpp index 8571bc492..1d4ee2464 100644 --- a/code/COBLoader.cpp +++ b/code/COBLoader.cpp @@ -487,46 +487,6 @@ void COBImporter::UnsupportedChunk_Ascii(LineSplitter& splitter, const ChunkInfo else ThrowException(error); } -// ------------------------------------------------------------------------------------------------ -void COBImporter::LogWarn_Ascii(const LineSplitter& splitter, const format& message) { - LogWarn_Ascii(message << " [at line "<< splitter.get_index()<<"]"); -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::LogError_Ascii(const LineSplitter& splitter, const format& message) { - LogError_Ascii(message << " [at line "<< splitter.get_index()<<"]"); -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::LogInfo_Ascii(const LineSplitter& splitter, const format& message) { - LogInfo_Ascii(message << " [at line "<< splitter.get_index()<<"]"); -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::LogDebug_Ascii(const LineSplitter& splitter, const format& message) { - LogDebug_Ascii(message << " [at line "<< splitter.get_index()<<"]"); -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::LogWarn_Ascii(const Formatter::format& message) { - ASSIMP_LOG_WARN_F( "COB: ", message ); -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::LogError_Ascii(const Formatter::format& message) { - ASSIMP_LOG_ERROR_F( "COB: ", message); -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::LogInfo_Ascii(const Formatter::format& message) { - ASSIMP_LOG_INFO_F("COB: ", message); -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::LogDebug_Ascii(const Formatter::format& message) { - ASSIMP_LOG_DEBUG_F("COB: ", message); -} - // ------------------------------------------------------------------------------------------------ void COBImporter::ReadBasicNodeInfo_Ascii(Node& msh, LineSplitter& splitter, const ChunkInfo& /*nfo*/) { @@ -576,8 +536,7 @@ void COBImporter::ReadMat1_Ascii(Scene& out, LineSplitter& splitter, const Chunk ++splitter; if (!splitter.match_start("mat# ")) { - LogWarn_Ascii(splitter,format()<< - "Expected `mat#` line in `Mat1` chunk "<unit_scale = t>=sizeof(units)/sizeof(units[0])?( - LogWarn_Ascii(splitter,format()<(reader.GetI1()); @@ -1289,16 +1238,13 @@ void COBImporter::ReadUnit_Binary(COB::Scene& out, StreamReaderLE& reader, const if (nd->id == nfo.parent_id) { const unsigned int t=reader.GetI2(); nd->unit_scale = t>=sizeof(units)/sizeof(units[0])?( - LogWarn_Ascii(format()<debug("CalcTangentsProcess begin"); + ASSIMP_LOG_DEBUG("CalcTangentsProcess begin"); bool bHas = false; for ( unsigned int a = 0; a < pScene->mNumMeshes; a++ ) { @@ -103,9 +103,9 @@ void CalcTangentsProcess::Execute( aiScene* pScene) } if ( bHas ) { - DefaultLogger::get()->info("CalcTangentsProcess finished. Tangents have been calculated"); + ASSIMP_LOG_INFO("CalcTangentsProcess finished. Tangents have been calculated"); } else { - DefaultLogger::get()->debug("CalcTangentsProcess finished"); + ASSIMP_LOG_DEBUG("CalcTangentsProcess finished"); } } @@ -126,19 +126,19 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) // are undefined. if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON))) { - DefaultLogger::get()->info("Tangents are undefined for line and point meshes"); + ASSIMP_LOG_INFO("Tangents are undefined for line and point meshes"); return false; } // what we can check, though, is if the mesh has normals and texture coordinates. That's a requirement if( pMesh->mNormals == NULL) { - DefaultLogger::get()->error("Failed to compute tangents; need normals"); + ASSIMP_LOG_ERROR("Failed to compute tangents; need normals"); return false; } if( configSourceUV >= AI_MAX_NUMBER_OF_TEXTURECOORDS || !pMesh->mTextureCoords[configSourceUV] ) { - DefaultLogger::get()->error((Formatter::format("Failed to compute tangents; need UV data in channel"),configSourceUV)); + ASSIMP_LOG_ERROR((Formatter::format("Failed to compute tangents; need UV data in channel"),configSourceUV)); return false; } diff --git a/code/ComputeUVMappingProcess.cpp b/code/ComputeUVMappingProcess.cpp index 6e778ddba..3b0577b2d 100644 --- a/code/ComputeUVMappingProcess.cpp +++ b/code/ComputeUVMappingProcess.cpp @@ -99,7 +99,7 @@ inline unsigned int FindEmptyUVChannel (aiMesh* mesh) for (unsigned int m = 0; m < AI_MAX_NUMBER_OF_TEXTURECOORDS;++m) if (!mesh->mTextureCoords[m])return m; - DefaultLogger::get()->error("Unable to compute UV coordinates, no free UV slot found"); + ASSIMP_LOG_ERROR("Unable to compute UV coordinates, no free UV slot found"); return UINT_MAX; } @@ -384,13 +384,13 @@ void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D& // ------------------------------------------------------------------------------------------------ void ComputeUVMappingProcess::ComputeBoxMapping( aiMesh*, aiVector3D* ) { - DefaultLogger::get()->error("Mapping type currently not implemented"); + ASSIMP_LOG_ERROR("Mapping type currently not implemented"); } // ------------------------------------------------------------------------------------------------ void ComputeUVMappingProcess::Execute( aiScene* pScene) { - DefaultLogger::get()->debug("GenUVCoordsProcess begin"); + ASSIMP_LOG_DEBUG("GenUVCoordsProcess begin"); char buffer[1024]; if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) @@ -418,7 +418,7 @@ void ComputeUVMappingProcess::Execute( aiScene* pScene) TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex, MappingTypeToString(mapping)); - DefaultLogger::get()->info(buffer); + ASSIMP_LOG_INFO(buffer); } if (aiTextureMapping_OTHER == mapping) @@ -485,7 +485,7 @@ void ComputeUVMappingProcess::Execute( aiScene* pScene) } if (m && idx != outIdx) { - DefaultLogger::get()->warn("UV index mismatch. Not all meshes assigned to " + ASSIMP_LOG_WARN("UV index mismatch. Not all meshes assigned to " "this material have equal numbers of UV channels. The UV index stored in " "the material structure does therefore not apply for all meshes. "); } @@ -502,5 +502,5 @@ void ComputeUVMappingProcess::Execute( aiScene* pScene) } } } - DefaultLogger::get()->debug("GenUVCoordsProcess finished"); + ASSIMP_LOG_DEBUG("GenUVCoordsProcess finished"); } diff --git a/code/ConvertToLHProcess.cpp b/code/ConvertToLHProcess.cpp index ba8371439..37ba970e4 100644 --- a/code/ConvertToLHProcess.cpp +++ b/code/ConvertToLHProcess.cpp @@ -85,7 +85,7 @@ void MakeLeftHandedProcess::Execute( aiScene* pScene) { // Check for an existent root node to proceed ai_assert(pScene->mRootNode != NULL); - DefaultLogger::get()->debug("MakeLeftHandedProcess begin"); + ASSIMP_LOG_DEBUG("MakeLeftHandedProcess begin"); // recursively convert all the nodes ProcessNode( pScene->mRootNode, aiMatrix4x4()); @@ -110,7 +110,7 @@ void MakeLeftHandedProcess::Execute( aiScene* pScene) ProcessAnimation( nodeAnim); } } - DefaultLogger::get()->debug("MakeLeftHandedProcess finished"); + ASSIMP_LOG_DEBUG("MakeLeftHandedProcess finished"); } // ------------------------------------------------------------------------------------------------ @@ -140,7 +140,7 @@ void MakeLeftHandedProcess::ProcessNode( aiNode* pNode, const aiMatrix4x4& pPare // Converts a single mesh to left handed coordinates. void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) { if ( nullptr == pMesh ) { - DefaultLogger::get()->error( "Nullptr to mesh found." ); + ASSIMP_LOG_ERROR( "Nullptr to mesh found." ); return; } // mirror positions, normals and stuff along the Z axis @@ -180,7 +180,7 @@ void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) { // Converts a single material to left handed coordinates. void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat) { if ( nullptr == _mat ) { - DefaultLogger::get()->error( "Nullptr to aiMaterial found." ); + ASSIMP_LOG_ERROR( "Nullptr to aiMaterial found." ); return; } @@ -245,13 +245,13 @@ bool FlipUVsProcess::IsActive( unsigned int pFlags) const // Executes the post processing step on the given imported data. void FlipUVsProcess::Execute( aiScene* pScene) { - DefaultLogger::get()->debug("FlipUVsProcess begin"); + ASSIMP_LOG_DEBUG("FlipUVsProcess begin"); for (unsigned int i = 0; i < pScene->mNumMeshes;++i) ProcessMesh(pScene->mMeshes[i]); for (unsigned int i = 0; i < pScene->mNumMaterials;++i) ProcessMaterial(pScene->mMaterials[i]); - DefaultLogger::get()->debug("FlipUVsProcess finished"); + ASSIMP_LOG_DEBUG("FlipUVsProcess finished"); } // ------------------------------------------------------------------------------------------------ @@ -262,7 +262,7 @@ void FlipUVsProcess::ProcessMaterial (aiMaterial* _mat) for (unsigned int a = 0; a < mat->mNumProperties;++a) { aiMaterialProperty* prop = mat->mProperties[a]; if( !prop ) { - DefaultLogger::get()->debug( "Property is null" ); + ASSIMP_LOG_DEBUG( "Property is null" ); continue; } @@ -319,10 +319,10 @@ bool FlipWindingOrderProcess::IsActive( unsigned int pFlags) const // Executes the post processing step on the given imported data. void FlipWindingOrderProcess::Execute( aiScene* pScene) { - DefaultLogger::get()->debug("FlipWindingOrderProcess begin"); + ASSIMP_LOG_DEBUG("FlipWindingOrderProcess begin"); for (unsigned int i = 0; i < pScene->mNumMeshes;++i) ProcessMesh(pScene->mMeshes[i]); - DefaultLogger::get()->debug("FlipWindingOrderProcess finished"); + ASSIMP_LOG_DEBUG("FlipWindingOrderProcess finished"); } // ------------------------------------------------------------------------------------------------ diff --git a/code/DeboneProcess.cpp b/code/DeboneProcess.cpp index 5a742dcf4..bc6afa36e 100644 --- a/code/DeboneProcess.cpp +++ b/code/DeboneProcess.cpp @@ -91,7 +91,7 @@ void DeboneProcess::SetupProperties(const Importer* pImp) // Executes the post processing step on the given imported data. void DeboneProcess::Execute( aiScene* pScene) { - DefaultLogger::get()->debug("DeboneProcess begin"); + ASSIMP_LOG_DEBUG("DeboneProcess begin"); if(!pScene->mNumMeshes) { return; @@ -148,9 +148,7 @@ void DeboneProcess::Execute( aiScene* pScene) } if(!DefaultLogger::isNullLogger()) { - char buffer[1024]; - ::ai_snprintf(buffer,1024,"Removed %u bones. Input bones: %u. Output bones: %u",in-out,in,out); - DefaultLogger::get()->info(buffer); + ASSIMP_LOG_INFO_F("Removed %u bones. Input bones:", in - out, ". Output bones: ", out); } // and destroy the source mesh. It should be completely contained inside the new submeshes @@ -173,7 +171,7 @@ void DeboneProcess::Execute( aiScene* pScene) UpdateNode( pScene->mRootNode); } - DefaultLogger::get()->debug("DeboneProcess end"); + ASSIMP_LOG_DEBUG("DeboneProcess end"); } // ------------------------------------------------------------------------------------------------ diff --git a/code/EmbedTexturesProcess.cpp b/code/EmbedTexturesProcess.cpp index 076339468..2fafc2de7 100644 --- a/code/EmbedTexturesProcess.cpp +++ b/code/EmbedTexturesProcess.cpp @@ -93,9 +93,7 @@ void EmbedTexturesProcess::Execute(aiScene* pScene) { } } - char stringBuffer[128]; - ::ai_snprintf(stringBuffer, 128, "EmbedTexturesProcess finished. Embedded %u textures.", embeddedTexturesCount); - DefaultLogger::get()->info(stringBuffer); + ASSIMP_LOG_INFO_F("EmbedTexturesProcess finished. Embedded ", embeddedTexturesCount, " textures." ); } bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const { @@ -105,7 +103,7 @@ bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const { // Test path directly std::ifstream file(imagePath, std::ios::binary | std::ios::ate); if ((imageSize = file.tellg()) == std::streampos(-1)) { - DefaultLogger::get()->warn("EmbedTexturesProcess: Cannot find image: " + imagePath + ". Will try to find it in root folder."); + ASSIMP_LOG_WARN_F("EmbedTexturesProcess: Cannot find image: ", imagePath, ". Will try to find it in root folder."); // Test path in root path imagePath = mRootPath + path; @@ -115,7 +113,7 @@ bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const { imagePath = mRootPath + path.substr(path.find_last_of("\\/") + 1u); file.open(imagePath, std::ios::binary | std::ios::ate); if ((imageSize = file.tellg()) == std::streampos(-1)) { - DefaultLogger::get()->error("EmbedTexturesProcess: Unable to embed texture: " + path + "."); + ASSIMP_LOG_ERROR_F("EmbedTexturesProcess: Unable to embed texture: ", path, "."); return false; } } diff --git a/code/FBXDocumentUtil.cpp b/code/FBXDocumentUtil.cpp index 3b1435b5c..b7de8d91d 100644 --- a/code/FBXDocumentUtil.cpp +++ b/code/FBXDocumentUtil.cpp @@ -91,7 +91,7 @@ void DOMWarning(const std::string& message, const Element* element /*= NULL*/) return; } if(DefaultLogger::get()) { - DefaultLogger::get()->warn("FBX-DOM: " + message); + ASSIMP_LOG_WARN("FBX-DOM: " + message); } } diff --git a/code/FindDegenerates.cpp b/code/FindDegenerates.cpp index dc2b5d01c..c0023c9a4 100644 --- a/code/FindDegenerates.cpp +++ b/code/FindDegenerates.cpp @@ -85,11 +85,11 @@ void FindDegeneratesProcess::SetupProperties(const Importer* pImp) { // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. void FindDegeneratesProcess::Execute( aiScene* pScene) { - DefaultLogger::get()->debug("FindDegeneratesProcess begin"); + ASSIMP_LOG_DEBUG("FindDegeneratesProcess begin"); for (unsigned int i = 0; i < pScene->mNumMeshes;++i){ ExecuteOnMesh( pScene->mMeshes[ i ] ); } - DefaultLogger::get()->debug("FindDegeneratesProcess finished"); + ASSIMP_LOG_DEBUG("FindDegeneratesProcess finished"); } static ai_real heron( ai_real a, ai_real b, ai_real c ) { @@ -242,7 +242,7 @@ evil_jump_outside: if (!mesh->mNumFaces) { // WTF!? // OK ... for completeness and because I'm not yet tired, - // let's write code that willl hopefully never be called + // let's write code that will hopefully never be called // (famous last words) // OK ... bad idea. @@ -250,10 +250,7 @@ evil_jump_outside: } } - if (deg && !DefaultLogger::isNullLogger()) - { - char s[64]; - ASSIMP_itoa10(s,deg); - DefaultLogger::get()->warn(std::string("Found ") + s + " degenerated primitives"); + if (deg && !DefaultLogger::isNullLogger()) { + ASSIMP_LOG_WARN_F( "Found ", deg, " degenerated primitives"); } } diff --git a/code/FindInstancesProcess.cpp b/code/FindInstancesProcess.cpp index 089e6c078..25dcc51e8 100644 --- a/code/FindInstancesProcess.cpp +++ b/code/FindInstancesProcess.cpp @@ -119,7 +119,7 @@ void UpdateMeshIndices(aiNode* node, unsigned int* lookup) // Executes the post processing step on the given imported data. void FindInstancesProcess::Execute( aiScene* pScene) { - DefaultLogger::get()->debug("FindInstancesProcess begin"); + ASSIMP_LOG_DEBUG("FindInstancesProcess begin"); if (pScene->mNumMeshes) { // use a pseudo hash for all meshes in the scene to quickly find @@ -267,13 +267,11 @@ void FindInstancesProcess::Execute( aiScene* pScene) // write to log if (!DefaultLogger::isNullLogger()) { - - char buffer[512]; - ::ai_snprintf(buffer,512,"FindInstancesProcess finished. Found %i instances",pScene->mNumMeshes-numMeshesOut); - DefaultLogger::get()->info(buffer); + ASSIMP_LOG_INFO_F( "FindInstancesProcess finished. Found ", (pScene->mNumMeshes - numMeshesOut), " instances" ); } pScene->mNumMeshes = numMeshesOut; + } else { + ASSIMP_LOG_DEBUG("FindInstancesProcess finished. No instanced meshes found"); } - else DefaultLogger::get()->debug("FindInstancesProcess finished. No instanced meshes found"); } } diff --git a/code/FindInvalidDataProcess.cpp b/code/FindInvalidDataProcess.cpp index 5e6b43dee..b1a296a54 100644 --- a/code/FindInvalidDataProcess.cpp +++ b/code/FindInvalidDataProcess.cpp @@ -118,7 +118,7 @@ void UpdateMeshReferences(aiNode* node, const std::vector& meshMap // Executes the post processing step on the given imported data. void FindInvalidDataProcess::Execute( aiScene* pScene) { - DefaultLogger::get()->debug("FindInvalidDataProcess begin"); + ASSIMP_LOG_DEBUG("FindInvalidDataProcess begin"); bool out = false; std::vector meshMapping(pScene->mNumMeshes); @@ -163,9 +163,10 @@ void FindInvalidDataProcess::Execute( aiScene* pScene) pScene->mNumMeshes = real; } - DefaultLogger::get()->info("FindInvalidDataProcess finished. Found issues ..."); + ASSIMP_LOG_INFO("FindInvalidDataProcess finished. Found issues ..."); + } else { + ASSIMP_LOG_DEBUG("FindInvalidDataProcess finished. Everything seems to be OK."); } - else DefaultLogger::get()->debug("FindInvalidDataProcess finished. Everything seems to be OK."); } // ------------------------------------------------------------------------------------------------ @@ -212,8 +213,7 @@ inline bool ProcessArray(T*& in, unsigned int num,const char* name, { const char* err = ValidateArrayContents(in,num,dirtyMask,mayBeIdentical,mayBeZero); if (err) { - DefaultLogger::get()->error(std::string("FindInvalidDataProcess fails on mesh ") + name + ": " + err); - + ASSIMP_LOG_ERROR_F( "FindInvalidDataProcess fails on mesh ", name, ": ", err); delete[] in; in = NULL; return true; @@ -354,7 +354,7 @@ int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh) // Process vertex positions if (pMesh->mVertices && ProcessArray(pMesh->mVertices, pMesh->mNumVertices, "positions", dirtyMask)) { - DefaultLogger::get()->error("Deleting mesh: Unable to continue without vertex positions"); + ASSIMP_LOG_ERROR("Deleting mesh: Unable to continue without vertex positions"); return 2; } diff --git a/code/FixNormalsStep.cpp b/code/FixNormalsStep.cpp index e66fec5ef..668b50c24 100644 --- a/code/FixNormalsStep.cpp +++ b/code/FixNormalsStep.cpp @@ -82,28 +82,35 @@ bool FixInfacingNormalsProcess::IsActive( unsigned int pFlags) const // Executes the post processing step on the given imported data. void FixInfacingNormalsProcess::Execute( aiScene* pScene) { - DefaultLogger::get()->debug("FixInfacingNormalsProcess begin"); + ASSIMP_LOG_DEBUG("FixInfacingNormalsProcess begin"); - bool bHas = false; - for( unsigned int a = 0; a < pScene->mNumMeshes; a++) - if(ProcessMesh( pScene->mMeshes[a],a))bHas = true; + bool bHas( false ); + for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) { + if (ProcessMesh(pScene->mMeshes[a], a)) { + bHas = true; + } + } - if (bHas) - DefaultLogger::get()->debug("FixInfacingNormalsProcess finished. Found issues."); - else DefaultLogger::get()->debug("FixInfacingNormalsProcess finished. No changes to the scene."); + if (bHas) { + ASSIMP_LOG_DEBUG("FixInfacingNormalsProcess finished. Found issues."); + } else { + ASSIMP_LOG_DEBUG("FixInfacingNormalsProcess finished. No changes to the scene."); + } } // ------------------------------------------------------------------------------------------------ // Apply the step to the mesh bool FixInfacingNormalsProcess::ProcessMesh( aiMesh* pcMesh, unsigned int index) { - ai_assert(NULL != pcMesh); + ai_assert(nullptr != pcMesh); // Nothing to do if there are no model normals - if (!pcMesh->HasNormals())return false; + if (!pcMesh->HasNormals()) { + return false; + } // Compute the bounding box of both the model vertices + normals and - // the umodified model vertices. Then check whether the first BB + // the unmodified model vertices. Then check whether the first BB // is smaller than the second. In this case we can assume that the // normals need to be flipped, although there are a few special cases .. // convex, concave, planar models ... @@ -155,14 +162,9 @@ bool FixInfacingNormalsProcess::ProcessMesh( aiMesh* pcMesh, unsigned int index) if (fDelta1_z < 0.05f * std::sqrt( fDelta1_y * fDelta1_x ))return false; // now compare the volumes of the bounding boxes - if (std::fabs(fDelta0_x * fDelta0_y * fDelta0_z) < - std::fabs(fDelta1_x * fDelta1_yz)) - { - if (!DefaultLogger::isNullLogger()) - { - char buffer[128]; // should be sufficiently large - ai_snprintf(buffer,128,"Mesh %u: Normals are facing inwards (or the mesh is planar)",index); - DefaultLogger::get()->info(buffer); + if (std::fabs(fDelta0_x * fDelta0_y * fDelta0_z) < std::fabs(fDelta1_x * fDelta1_yz)) { + if (!DefaultLogger::isNullLogger()) { + ASSIMP_LOG_INFO_F("Mesh ", index, ": Normals are facing inwards (or the mesh is planar)", index); } // Invert normals diff --git a/code/GenFaceNormalsProcess.cpp b/code/GenFaceNormalsProcess.cpp index be726302c..2639868f1 100644 --- a/code/GenFaceNormalsProcess.cpp +++ b/code/GenFaceNormalsProcess.cpp @@ -72,16 +72,14 @@ GenFaceNormalsProcess::~GenFaceNormalsProcess() // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool GenFaceNormalsProcess::IsActive( unsigned int pFlags) const -{ +bool GenFaceNormalsProcess::IsActive( unsigned int pFlags) const { return (pFlags & aiProcess_GenNormals) != 0; } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void GenFaceNormalsProcess::Execute( aiScene* pScene) -{ - DefaultLogger::get()->debug("GenFaceNormalsProcess begin"); +void GenFaceNormalsProcess::Execute( aiScene* pScene) { + ASSIMP_LOG_DEBUG("GenFaceNormalsProcess begin"); if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) { throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here"); @@ -94,11 +92,12 @@ void GenFaceNormalsProcess::Execute( aiScene* pScene) } } if (bHas) { - DefaultLogger::get()->info("GenFaceNormalsProcess finished. " + ASSIMP_LOG_INFO("GenFaceNormalsProcess finished. " "Face normals have been calculated"); + } else { + ASSIMP_LOG_DEBUG("GenFaceNormalsProcess finished. " + "Normals are already there"); } - else DefaultLogger::get()->debug("GenFaceNormalsProcess finished. " - "Normals are already there"); } // ------------------------------------------------------------------------------------------------ @@ -113,7 +112,7 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh) // triangles or higher-order polygons the normal vectors // are undefined. if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON))) { - DefaultLogger::get()->info("Normal vectors are undefined for line and point meshes"); + ASSIMP_LOG_INFO("Normal vectors are undefined for line and point meshes"); return false; } diff --git a/code/GenVertexNormalsProcess.cpp b/code/GenVertexNormalsProcess.cpp index f746f3776..7f29411c3 100644 --- a/code/GenVertexNormalsProcess.cpp +++ b/code/GenVertexNormalsProcess.cpp @@ -88,24 +88,25 @@ void GenVertexNormalsProcess::SetupProperties(const Importer* pImp) // Executes the post processing step on the given imported data. void GenVertexNormalsProcess::Execute( aiScene* pScene) { - DefaultLogger::get()->debug("GenVertexNormalsProcess begin"); + ASSIMP_LOG_DEBUG("GenVertexNormalsProcess begin"); - if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) + if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) { throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here"); + } bool bHas = false; - for( unsigned int a = 0; a < pScene->mNumMeshes; a++) - { + for( unsigned int a = 0; a < pScene->mNumMeshes; ++a) { if(GenMeshVertexNormals( pScene->mMeshes[a],a)) bHas = true; } if (bHas) { - DefaultLogger::get()->info("GenVertexNormalsProcess finished. " + ASSIMP_LOG_INFO("GenVertexNormalsProcess finished. " "Vertex normals have been calculated"); + } else { + ASSIMP_LOG_DEBUG("GenVertexNormalsProcess finished. " + "Normals are already there"); } - else DefaultLogger::get()->debug("GenVertexNormalsProcess finished. " - "Normals are already there"); } // ------------------------------------------------------------------------------------------------ @@ -120,7 +121,7 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int // are undefined. if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON))) { - DefaultLogger::get()->info("Normal vectors are undefined for line and point meshes"); + ASSIMP_LOG_INFO("Normal vectors are undefined for line and point meshes"); return false; } diff --git a/code/IRRMeshLoader.cpp b/code/IRRMeshLoader.cpp index 1ed16acd6..85de42195 100644 --- a/code/IRRMeshLoader.cpp +++ b/code/IRRMeshLoader.cpp @@ -470,7 +470,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile, } if (curFace != faceEnd) - DefaultLogger::get()->error("IRRMESH: Not enough indices"); + ASSIMP_LOG_ERROR("IRRMESH: Not enough indices"); // Finish processing the mesh - do some small material workarounds if (curMatFlags & AI_IRRMESH_MAT_trans_vertex_alpha && !useColors) { diff --git a/code/Importer.cpp b/code/Importer.cpp index 36afc8723..9fbba61c4 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -510,45 +510,46 @@ void WriteLogOpening(const std::string& file) // need to ask the authors of incoming bug reports for // the library version they're using - a log dump is // sufficient. - const unsigned int flags = aiGetCompileFlags(); - ASSIMP_LOG_DEBUG_F( "Assimp ", aiGetVersionMajor(), ".", aiGetVersionMinor(), ".", aiGetVersionRevision(), " " + const unsigned int flags( aiGetCompileFlags() ); + std::stringstream stream; + stream << "Assimp " << aiGetVersionMajor() << "." << aiGetVersionMinor() << "." << aiGetVersionRevision() << " " #if defined(ASSIMP_BUILD_ARCHITECTURE) - ,ASSIMP_BUILD_ARCHITECTURE + << ASSIMP_BUILD_ARCHITECTURE #elif defined(_M_IX86) || defined(__x86_32__) || defined(__i386__) - , "x86" + << "x86" #elif defined(_M_X64) || defined(__x86_64__) - , "amd64" + << "amd64" #elif defined(_M_IA64) || defined(__ia64__) - , "itanium" + << "itanium" #elif defined(__ppc__) || defined(__powerpc__) - , "ppc32" + << "ppc32" #elif defined(__powerpc64__) - , "ppc64" + << "ppc64" #elif defined(__arm__) - , "arm" + << "arm" #else - , "" + << "" #endif - - , " " + << " " #if defined(ASSIMP_BUILD_COMPILER) - , ASSIMP_BUILD_COMPILER + << ( ASSIMP_BUILD_COMPILER ) #elif defined(_MSC_VER) - , "msvc" + << "msvc" #elif defined(__GNUC__) - , "gcc" + << "gcc" #else - , "" + << "" #endif #ifdef ASSIMP_BUILD_DEBUG - , " debug" + << " debug" #endif - , (flags & ASSIMP_CFLAGS_NOBOOST ? " noboost" : "") - , (flags & ASSIMP_CFLAGS_SHARED ? " shared" : "") - , (flags & ASSIMP_CFLAGS_SINGLETHREADED ? " singlethreaded" : "") - ); + << (flags & ASSIMP_CFLAGS_NOBOOST ? " noboost" : "") + << (flags & ASSIMP_CFLAGS_SHARED ? " shared" : "") + << (flags & ASSIMP_CFLAGS_SINGLETHREADED ? " singlethreaded" : ""); + + ASSIMP_LOG_DEBUG(stream.str()); } // ------------------------------------------------------------------------------------------------ diff --git a/code/ImproveCacheLocality.cpp b/code/ImproveCacheLocality.cpp index ef16aeac9..781462a92 100644 --- a/code/ImproveCacheLocality.cpp +++ b/code/ImproveCacheLocality.cpp @@ -95,11 +95,11 @@ void ImproveCacheLocalityProcess::SetupProperties(const Importer* pImp) void ImproveCacheLocalityProcess::Execute( aiScene* pScene) { if (!pScene->mNumMeshes) { - DefaultLogger::get()->debug("ImproveCacheLocalityProcess skipped; there are no meshes"); + ASSIMP_LOG_DEBUG("ImproveCacheLocalityProcess skipped; there are no meshes"); return; } - DefaultLogger::get()->debug("ImproveCacheLocalityProcess begin"); + ASSIMP_LOG_DEBUG("ImproveCacheLocalityProcess begin"); float out = 0.f; unsigned int numf = 0, numm = 0; @@ -112,12 +112,8 @@ void ImproveCacheLocalityProcess::Execute( aiScene* pScene) } } if (!DefaultLogger::isNullLogger()) { - char szBuff[128]; // should be sufficiently large in every case - ai_snprintf(szBuff,128,"Cache relevant are %u meshes (%u faces). Average output ACMR is %f", - numm,numf,out/numf); - - DefaultLogger::get()->info(szBuff); - DefaultLogger::get()->debug("ImproveCacheLocalityProcess finished. "); + ASSIMP_LOG_INFO_F("Cache relevant are ", numm, " meshes (", numf," faces). Average output ACMR is ", out / numf ); + ASSIMP_LOG_DEBUG("ImproveCacheLocalityProcess finished. "); } } @@ -135,7 +131,7 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh return 0.f; if (pMesh->mPrimitiveTypes != aiPrimitiveType_TRIANGLE) { - DefaultLogger::get()->error("This algorithm works on triangle meshes only"); + ASSIMP_LOG_ERROR("This algorithm works on triangle meshes only"); return 0.f; } @@ -363,11 +359,7 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh // very intense verbose logging ... prepare for much text if there are many meshes if ( DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) { - char szBuff[128]; // should be sufficiently large in every case - - ai_snprintf(szBuff,128,"Mesh %u | ACMR in: %f out: %f | ~%.1f%%",meshNum,fACMR,fACMR2, - ((fACMR - fACMR2) / fACMR) * 100.f); - DefaultLogger::get()->debug(szBuff); + ASSIMP_LOG_DEBUG_F("Mesh %u | ACMR in: ", meshNum, " out: ", fACMR, " | ~", fACMR2, ((fACMR - fACMR2) / fACMR) * 100.f); } fACMR2 *= pMesh->mNumFaces; diff --git a/code/JoinVerticesProcess.cpp b/code/JoinVerticesProcess.cpp index 3ab5d5833..1bbd18145 100644 --- a/code/JoinVerticesProcess.cpp +++ b/code/JoinVerticesProcess.cpp @@ -79,7 +79,7 @@ bool JoinVerticesProcess::IsActive( unsigned int pFlags) const // Executes the post processing step on the given imported data. void JoinVerticesProcess::Execute( aiScene* pScene) { - DefaultLogger::get()->debug("JoinVerticesProcess begin"); + ASSIMP_LOG_DEBUG("JoinVerticesProcess begin"); // get the total number of vertices BEFORE the step is executed int iNumOldVertices = 0; @@ -95,19 +95,13 @@ void JoinVerticesProcess::Execute( aiScene* pScene) iNumVertices += ProcessMesh( pScene->mMeshes[a],a); // if logging is active, print detailed statistics - if (!DefaultLogger::isNullLogger()) - { - if (iNumOldVertices == iNumVertices) - { - DefaultLogger::get()->debug("JoinVerticesProcess finished "); - } else - { - char szBuff[128]; // should be sufficiently large in every case - ::ai_snprintf(szBuff,128,"JoinVerticesProcess finished | Verts in: %i out: %i | ~%.1f%%", - iNumOldVertices, - iNumVertices, - ((iNumOldVertices - iNumVertices) / (float)iNumOldVertices) * 100.f); - DefaultLogger::get()->info(szBuff); + if (!DefaultLogger::isNullLogger()) { + if (iNumOldVertices == iNumVertices) { + ASSIMP_LOG_DEBUG("JoinVerticesProcess finished "); + } else { + ASSIMP_LOG_INFO_F("JoinVerticesProcess finished | Verts in: ", iNumOldVertices, + " out: ", iNumVertices, " | ~", + ((iNumOldVertices - iNumVertices) / (float)iNumOldVertices) * 100.f ); } } @@ -274,7 +268,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) } if (!DefaultLogger::isNullLogger() && DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) { - DefaultLogger::get()->debug((Formatter::format(), + ASSIMP_LOG_DEBUG_F( "Mesh ",meshIndex, " (", (pMesh->mName.length ? pMesh->mName.data : "unnamed"), @@ -284,7 +278,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) " | ~", ((pMesh->mNumVertices - uniqueVertices.size()) / (float)pMesh->mNumVertices) * 100.f, "%" - )); + ); } // replace vertex data with the unique data sets @@ -375,7 +369,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) } } } else { - DefaultLogger::get()->error( "X-Export: aiBone shall contain weights, but pointer to them is NULL." ); + ASSIMP_LOG_ERROR( "X-Export: aiBone shall contain weights, but pointer to them is NULL." ); } if (newWeights.size() > 0) { diff --git a/code/LWOLoader.cpp b/code/LWOLoader.cpp index d654935b4..fbefe4a1e 100644 --- a/code/LWOLoader.cpp +++ b/code/LWOLoader.cpp @@ -1080,7 +1080,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) // we have already a VMAP entry for this vertex - thus // we need to duplicate the corresponding polygon. if (polyIdx >= numFaces) { - DefaultLogger::get()->warn("LWO2: Failure evaluating VMAD entry \'" + name + "\', polygon index is out of range"); + ASSIMP_LOG_WARN_F("LWO2: Failure evaluating VMAD entry \'", name, "\', polygon index is out of range"); mFileBuffer += base->dims<<2u; continue; } @@ -1442,17 +1442,21 @@ void LWOImporter::LoadLWO2File() if (skip) break; - if (mCurLayer->mFaces.empty()) - DefaultLogger::get()->warn("LWO2: Unexpected PTAG"); - else LoadLWO2PolygonTags(head.length); + if (mCurLayer->mFaces.empty()) { + ASSIMP_LOG_WARN("LWO2: Unexpected PTAG"); + } else { + LoadLWO2PolygonTags(head.length); + } break; } // list of tags case AI_LWO_TAGS: { - if (!mTags->empty()) + if (!mTags->empty()) { ASSIMP_LOG_WARN("LWO2: SRFS chunk encountered twice"); - else LoadLWOTags(head.length); + } else { + LoadLWOTags(head.length); + } break; } diff --git a/code/LWSLoader.cpp b/code/LWSLoader.cpp index 4313359d8..518b893e9 100644 --- a/code/LWSLoader.cpp +++ b/code/LWSLoader.cpp @@ -684,7 +684,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, (*it).tokens[0] == "LightMotion")) { if (nodes.empty()) - DASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'Motion\'"); + ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'Motion\'"); else { ReadEnvelope_Old(it,root.children.end(),nodes.back(),version); } @@ -773,7 +773,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, // 'LightType': set type of currently active light else if ((*it).tokens[0] == "LightType") { if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightType\'"); + ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightType\'"); else nodes.back().lightType = strtoul10(c); diff --git a/code/LimitBoneWeightsProcess.cpp b/code/LimitBoneWeightsProcess.cpp index 8c21f2394..cc87e407c 100644 --- a/code/LimitBoneWeightsProcess.cpp +++ b/code/LimitBoneWeightsProcess.cpp @@ -76,13 +76,13 @@ bool LimitBoneWeightsProcess::IsActive( unsigned int pFlags) const // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void LimitBoneWeightsProcess::Execute( aiScene* pScene) -{ - DefaultLogger::get()->debug("LimitBoneWeightsProcess begin"); - for( unsigned int a = 0; a < pScene->mNumMeshes; a++) - ProcessMesh( pScene->mMeshes[a]); +void LimitBoneWeightsProcess::Execute( aiScene* pScene) { + ASSIMP_LOG_DEBUG("LimitBoneWeightsProcess begin"); + for (unsigned int a = 0; a < pScene->mNumMeshes; ++a ) { + ProcessMesh(pScene->mMeshes[a]); + } - DefaultLogger::get()->debug("LimitBoneWeightsProcess end"); + ASSIMP_LOG_DEBUG("LimitBoneWeightsProcess end"); } // ------------------------------------------------------------------------------------------------ @@ -195,9 +195,7 @@ void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh) } if (!DefaultLogger::isNullLogger()) { - char buffer[1024]; - ai_snprintf(buffer,1024,"Removed %u weights. Input bones: %u. Output bones: %u",removed,old_bones,pMesh->mNumBones); - DefaultLogger::get()->info(buffer); + ASSIMP_LOG_INFO_F("Removed ", removed, " weights. Input bones: ", old_bones, ". Output bones: ", pMesh->mNumBones ); } } } diff --git a/code/MD5Parser.cpp b/code/MD5Parser.cpp index 7fa4db1ba..6f942228c 100644 --- a/code/MD5Parser.cpp +++ b/code/MD5Parser.cpp @@ -130,7 +130,7 @@ void MD5Parser::ParseHeader() // FIX: can break the log length limit, so we need to be careful char* sz = buffer; while (!IsLineEnd( *buffer++)); - DefaultLogger::get()->info(std::string(sz,std::min((uintptr_t)MAX_LOG_MESSAGE_LENGTH, (uintptr_t)(buffer-sz)))); + ASSIMP_LOG_INFO(std::string(sz,std::min((uintptr_t)MAX_LOG_MESSAGE_LENGTH, (uintptr_t)(buffer-sz)))); SkipSpacesAndLineEnd(); } @@ -483,6 +483,6 @@ MD5CameraParser::MD5CameraParser(SectionList& mSections) } } } - DefaultLogger::get()->debug("MD5CameraParser end"); + ASSIMP_LOG_DEBUG("MD5CameraParser end"); } diff --git a/code/MDCLoader.cpp b/code/MDCLoader.cpp index 34ead53a9..e294a1912 100644 --- a/code/MDCLoader.cpp +++ b/code/MDCLoader.cpp @@ -159,8 +159,9 @@ void MDCImporter::ValidateHeader() "magic word found is " + std::string( szBuffer )); } - if (pcHeader->ulVersion != AI_MDC_VERSION) - DefaultLogger::get()->warn("Unsupported MDC file version (2 (AI_MDC_VERSION) was expected)"); + if (pcHeader->ulVersion != AI_MDC_VERSION) { + ASSIMP_LOG_WARN("Unsupported MDC file version (2 (AI_MDC_VERSION) was expected)"); + } if (pcHeader->ulOffsetBorderFrames + pcHeader->ulNumFrames * sizeof(MDC::Frame) > this->fileSize || pcHeader->ulOffsetSurfaces + pcHeader->ulNumSurfaces * sizeof(MDC::Surface) > this->fileSize) @@ -169,8 +170,9 @@ void MDCImporter::ValidateHeader() "and point to something behind the file."); } - if (this->configFrameID >= this->pcHeader->ulNumFrames) + if (this->configFrameID >= this->pcHeader->ulNumFrames) { throw DeadlyImportError("The requested frame is not available"); + } } // ------------------------------------------------------------------------------------------------ @@ -388,7 +390,7 @@ void MDCImporter::InternReadFile( uint32_t quak = pcTriangle->aiIndices[iIndex]; if (quak >= pcSurface->ulNumVertices) { - DefaultLogger::get()->error("MDC vertex index is out of range"); + ASSIMP_LOG_ERROR("MDC vertex index is out of range"); quak = pcSurface->ulNumVertices-1; } diff --git a/code/MDLLoader.cpp b/code/MDLLoader.cpp index aed244bc2..4c43bc64f 100644 --- a/code/MDLLoader.cpp +++ b/code/MDLLoader.cpp @@ -481,7 +481,7 @@ void MDLImporter::InternReadFile_Quake1() { if (iIndex >= (unsigned int)pcHeader->num_verts) { iIndex = pcHeader->num_verts-1; - DefaultLogger::get()->warn("Index overflow in Q1-MDL vertex list."); + ASSIMP_LOG_WARN("Index overflow in Q1-MDL vertex list."); } aiVector3D& vec = pcMesh->mVertices[iCurrent]; @@ -1026,7 +1026,7 @@ void MDLImporter::ReadFaces_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo, if(iIndex > (unsigned int)groupInfo.pcGroup->numverts) { // (we might need to read this section a second time - to process frame vertices correctly) pcGroupTris->v_index[c] = iIndex = groupInfo.pcGroup->numverts-1; - DASSIMP_LOG_WARN("Index overflow in MDL7 vertex list"); + ASSIMP_LOG_WARN("Index overflow in MDL7 vertex list"); } // write the output face index @@ -1894,7 +1894,7 @@ void MDLImporter::GenerateOutputMeshes_3DGS_MDL7( unsigned int iBone = groupData.aiBones[ oldFace.mIndices[c] ]; if (UINT_MAX != iBone) { if (iBone >= iNumOutBones) { - DefaultLogger::get()->error("Bone index overflow. " + ASSIMP_LOG_ERROR("Bone index overflow. " "The bone index of a vertex exceeds the allowed range. "); iBone = iNumOutBones-1; } diff --git a/code/MDLMaterialLoader.cpp b/code/MDLMaterialLoader.cpp index 8955455ef..e80d3b560 100644 --- a/code/MDLMaterialLoader.cpp +++ b/code/MDLMaterialLoader.cpp @@ -64,7 +64,7 @@ using namespace Assimp; static aiTexel* const bad_texel = reinterpret_cast(SIZE_MAX); // ------------------------------------------------------------------------------------------------ -// Find a suitable pallette file or take the default one +// Find a suitable palette file or take the default one void MDLImporter::SearchPalette(const unsigned char** pszColorMap) { // now try to find the color map in the current directory @@ -75,10 +75,11 @@ void MDLImporter::SearchPalette(const unsigned char** pszColorMap) { if (pcStream->FileSize() >= 768) { - unsigned char* colorMap = new unsigned char[256*3]; + constexpr size_t len = 256 * 3; + unsigned char* colorMap = new unsigned char[len]; szColorMap = colorMap; - pcStream->Read(colorMap,256*3,1); - DefaultLogger::get()->info("Found valid colormap.lmp in directory. " + pcStream->Read(colorMap, len,1); + ASSIMP_LOG_INFO("Found valid colormap.lmp in directory. " "It will be used to decode embedded textures in palletized formats."); } delete pcStream; @@ -186,7 +187,7 @@ void MDLImporter::CreateTexture_3DGS_MDL4(const unsigned char* szData, if (iType == 1 || iType > 3) { - DefaultLogger::get()->error("Unsupported texture file format"); + ASSIMP_LOG_ERROR("Unsupported texture file format"); return; } @@ -508,7 +509,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7( // ***** EMBEDDED DDS FILE ***** if (1 != iHeight) { - DefaultLogger::get()->warn("Found a reference to an embedded DDS texture, " + ASSIMP_LOG_WARN("Found a reference to an embedded DDS texture, " "but texture height is not equal to 1, which is not supported by MED"); } diff --git a/code/MS3DLoader.cpp b/code/MS3DLoader.cpp index 869c41afb..b06bea31c 100644 --- a/code/MS3DLoader.cpp +++ b/code/MS3DLoader.cpp @@ -349,9 +349,6 @@ void MS3DImporter::InternReadFile( const std::string& pFile, stream.CopyAndAdvance(j.parentName,32); j.parentName[32] = '\0'; - // DefaultLogger::get()->debug(j.name); - // DefaultLogger::get()->debug(j.parentName); - ReadVector(stream,j.rotation); ReadVector(stream,j.position); @@ -386,7 +383,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile, } const std::string& s = std::string(reinterpret_cast(stream.GetPtr()),len); - DefaultLogger::get()->debug("MS3D: Model comment: " + s); + ASSIMP_LOG_DEBUG_F("MS3D: Model comment: ", s); } if(stream.GetRemainingSize() > 4 && inrange((stream >> subversion,subversion),1u,3u)) { diff --git a/code/MakeVerboseFormat.cpp b/code/MakeVerboseFormat.cpp index f6a978e56..b6f5cabd9 100644 --- a/code/MakeVerboseFormat.cpp +++ b/code/MakeVerboseFormat.cpp @@ -65,7 +65,7 @@ MakeVerboseFormatProcess::~MakeVerboseFormatProcess() void MakeVerboseFormatProcess::Execute( aiScene* pScene) { ai_assert(NULL != pScene); - DefaultLogger::get()->debug("MakeVerboseFormatProcess begin"); + ASSIMP_LOG_DEBUG("MakeVerboseFormatProcess begin"); bool bHas = false; for( unsigned int a = 0; a < pScene->mNumMeshes; a++) @@ -73,12 +73,15 @@ void MakeVerboseFormatProcess::Execute( aiScene* pScene) if( MakeVerboseFormat( pScene->mMeshes[a])) bHas = true; } - if (bHas) DefaultLogger::get()->info("MakeVerboseFormatProcess finished. There was much work to do ..."); - else DefaultLogger::get()->debug("MakeVerboseFormatProcess. There was nothing to do."); + if (bHas) { + ASSIMP_LOG_INFO("MakeVerboseFormatProcess finished. There was much work to do ..."); + } else { + ASSIMP_LOG_DEBUG("MakeVerboseFormatProcess. There was nothing to do."); + } pScene->mFlags &= ~AI_SCENE_FLAGS_NON_VERBOSE_FORMAT; - } + // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh) diff --git a/code/NDOLoader.cpp b/code/NDOLoader.cpp index 1e6c1e2ca..17c9e135b 100644 --- a/code/NDOLoader.cpp +++ b/code/NDOLoader.cpp @@ -130,18 +130,18 @@ void NDOImporter::InternReadFile( const std::string& pFile, unsigned int file_format = 12; if (!strncmp("1.0",head+6,3)) { file_format = 10; - DefaultLogger::get()->info("NDO file format is 1.0"); + ASSIMP_LOG_INFO("NDO file format is 1.0"); } else if (!strncmp("1.1",head+6,3)) { file_format = 11; - DefaultLogger::get()->info("NDO file format is 1.1"); + ASSIMP_LOG_INFO("NDO file format is 1.1"); } else if (!strncmp("1.2",head+6,3)) { file_format = 12; - DefaultLogger::get()->info("NDO file format is 1.2"); + ASSIMP_LOG_INFO("NDO file format is 1.2"); } else { - ASSIMP_LOG_WARN(std::string("Unrecognized nendo file format version, continuing happily ... :") + (head+6)); + ASSIMP_LOG_WARN_F( "Unrecognized nendo file format version, continuing happily ... :", (head+6)); } reader.IncPtr(2); /* skip flags */ diff --git a/code/NFFLoader.cpp b/code/NFFLoader.cpp index 39f336112..2c7eeaa20 100644 --- a/code/NFFLoader.cpp +++ b/code/NFFLoader.cpp @@ -132,7 +132,7 @@ const aiImporterDesc* NFFImporter::GetInfo () const // ------------------------------------------------------------------------------------------------ -// Loads the materail table for the NFF2 file format from an external file +// Loads the material table for the NFF2 file format from an external file void NFFImporter::LoadNFF2MaterialTable(std::vector& output, const std::string& path, IOSystem* pIOHandler) { @@ -140,7 +140,7 @@ void NFFImporter::LoadNFF2MaterialTable(std::vector& output, // Check whether we can read from the file if( !file.get()) { - DefaultLogger::get()->error("NFF2: Unable to open material library " + path + "."); + ASSIMP_LOG_ERROR("NFF2: Unable to open material library " + path + "."); return; } @@ -158,7 +158,7 @@ void NFFImporter::LoadNFF2MaterialTable(std::vector& output, // The file should start with the magic sequence "mat" if (!TokenMatch(buffer,"mat",3)) { - DefaultLogger::get()->error("NFF2: Not a valid material library " + path + "."); + ASSIMP_LOG_ERROR_F("NFF2: Not a valid material library ", path, "."); return; } @@ -174,7 +174,7 @@ void NFFImporter::LoadNFF2MaterialTable(std::vector& output, // 'version' defines the version of the file format if (TokenMatch(sz,"version",7)) { - DefaultLogger::get()->info("NFF (Sense8) material library file format: " + std::string(sz)); + ASSIMP_LOG_INFO_F("NFF (Sense8) material library file format: ", std::string(sz)); } // 'matdef' starts a new material in the file else if (TokenMatch(sz,"matdef",6)) @@ -192,8 +192,7 @@ void NFFImporter::LoadNFF2MaterialTable(std::vector& output, { if (!curShader) { - DefaultLogger::get()->error(std::string("NFF2 material library: Found element ") + - sz + "but there is no active material"); + ASSIMP_LOG_ERROR_F("NFF2 material library: Found element ", sz, "but there is no active material"); continue; } } @@ -308,7 +307,7 @@ void NFFImporter::InternReadFile( const std::string& pFile, SkipSpaces(line,&sz); if (TokenMatch(sz,"version",7)) { - DefaultLogger::get()->info("NFF (Sense8) file format: " + std::string(sz)); + ASSIMP_LOG_INFO_F("NFF (Sense8) file format: ", sz ); } else if (TokenMatch(sz,"viewpos",7)) { @@ -471,7 +470,7 @@ void NFFImporter::InternReadFile( const std::string& pFile, unsigned int m = ::strtoul10(sz,&sz); if (m >= (unsigned int)tempPositions.size()) { - DefaultLogger::get()->error("NFF2: Vertex index overflow"); + ASSIMP_LOG_ERROR("NFF2: Vertex index overflow"); m= 0; } // mesh.vertices.push_back (tempPositions[idx]); @@ -577,7 +576,7 @@ void NFFImporter::InternReadFile( const std::string& pFile, matIdx = ::strtoul10(sz,&sz); if (matIdx >= materialTable.size()) { - DefaultLogger::get()->error("NFF2: Material index overflow."); + ASSIMP_LOG_ERROR("NFF2: Material index overflow."); matIdx = 0; } @@ -750,7 +749,7 @@ void NFFImporter::InternReadFile( const std::string& pFile, { if(!GetNextLine(buffer,line)) { - DefaultLogger::get()->error("NFF: Unexpected EOF was encountered. Patch definition incomplete"); + ASSIMP_LOG_ERROR("NFF: Unexpected EOF was encountered. Patch definition incomplete"); continue; } @@ -943,7 +942,7 @@ void NFFImporter::InternReadFile( const std::string& pFile, if(!GetNextLine(buffer,line)) { - DefaultLogger::get()->error("NFF: Unexpected end of file (cone definition not complete)"); + ASSIMP_LOG_ERROR("NFF: Unexpected end of file (cone definition not complete)"); break; } sz = line; @@ -955,7 +954,7 @@ void NFFImporter::InternReadFile( const std::string& pFile, if(!GetNextLine(buffer,line)) { - DefaultLogger::get()->error("NFF: Unexpected end of file (cone definition not complete)"); + ASSIMP_LOG_ERROR("NFF: Unexpected end of file (cone definition not complete)"); break; } sz = line; @@ -971,7 +970,7 @@ void NFFImporter::InternReadFile( const std::string& pFile, float f; if (( f = currentMesh.dir.Length()) < 10e-3f ) { - DefaultLogger::get()->error("NFF: Cone height is close to zero"); + ASSIMP_LOG_ERROR("NFF: Cone height is close to zero"); continue; } currentMesh.dir /= f; // normalize @@ -1029,18 +1028,20 @@ void NFFImporter::InternReadFile( const std::string& pFile, // 'pb' - bezier patch. Not supported yet else if (TokenMatch(sz,"pb",2)) { - DefaultLogger::get()->error("NFF: Encountered unsupported ID: bezier patch"); + ASSIMP_LOG_ERROR("NFF: Encountered unsupported ID: bezier patch"); } // 'pn' - NURBS. Not supported yet else if (TokenMatch(sz,"pn",2) || TokenMatch(sz,"pnn",3)) { - DefaultLogger::get()->error("NFF: Encountered unsupported ID: NURBS"); + ASSIMP_LOG_ERROR("NFF: Encountered unsupported ID: NURBS"); } // '' - comment else if ('#' == line[0]) { const char* sz;SkipSpaces(&line[1],&sz); - if (!IsLineEnd(*sz))DefaultLogger::get()->info(sz); + if (!IsLineEnd(*sz)) { + ASSIMP_LOG_INFO(sz); + } } } } diff --git a/code/OFFLoader.cpp b/code/OFFLoader.cpp index d99ba55a2..81f9c9916 100644 --- a/code/OFFLoader.cpp +++ b/code/OFFLoader.cpp @@ -157,7 +157,7 @@ void OFFImporter::InternReadFile( const std::string& pFile, { if(!GetNextLine(buffer,line)) { - DefaultLogger::get()->error("OFF: The number of verts in the header is incorrect"); + ASSIMP_LOG_ERROR("OFF: The number of verts in the header is incorrect"); break; } aiVector3D& v = tempPositions[i]; @@ -175,14 +175,14 @@ void OFFImporter::InternReadFile( const std::string& pFile, { if(!GetNextLine(buffer,line)) { - DefaultLogger::get()->error("OFF: The number of faces in the header is incorrect"); + ASSIMP_LOG_ERROR("OFF: The number of faces in the header is incorrect"); break; } sz = line;SkipSpaces(&sz); faces->mNumIndices = strtoul10(sz,&sz); if(!(faces->mNumIndices) || faces->mNumIndices > 9) { - DefaultLogger::get()->error("OFF: Faces with zero indices aren't allowed"); + ASSIMP_LOG_ERROR("OFF: Faces with zero indices aren't allowed"); --mesh->mNumFaces; continue; } @@ -217,7 +217,7 @@ void OFFImporter::InternReadFile( const std::string& pFile, idx = strtoul10(sz,&sz); if ((idx) >= numVertices) { - DefaultLogger::get()->error("OFF: Vertex index is out of range"); + ASSIMP_LOG_ERROR("OFF: Vertex index is out of range"); idx = numVertices-1; } faces->mIndices[m] = p++; diff --git a/code/ObjFileImporter.cpp b/code/ObjFileImporter.cpp index bce94ebbb..dd0733caa 100644 --- a/code/ObjFileImporter.cpp +++ b/code/ObjFileImporter.cpp @@ -557,7 +557,7 @@ void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pSc const unsigned int numMaterials = (unsigned int) pModel->m_MaterialLib.size(); pScene->mNumMaterials = 0; if ( pModel->m_MaterialLib.empty() ) { - DefaultLogger::get()->debug("OBJ: no materials specified"); + ASSIMP_LOG_DEBUG("OBJ: no materials specified"); return; } @@ -591,7 +591,7 @@ void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pSc break; default: sm = aiShadingMode_Gouraud; - DefaultLogger::get()->error("OBJ: unexpected illumination model (0-2 recognized)"); + ASSIMP_LOG_ERROR("OBJ: unexpected illumination model (0-2 recognized)"); } mat->AddProperty( &sm, 1, AI_MATKEY_SHADING_MODEL); diff --git a/code/ObjFileMtlImporter.cpp b/code/ObjFileMtlImporter.cpp index 584b3115c..8f7588819 100644 --- a/code/ObjFileMtlImporter.cpp +++ b/code/ObjFileMtlImporter.cpp @@ -366,7 +366,7 @@ void ObjFileMtlImporter::getTexture() { out = & m_pModel->m_pCurrentMaterial->textureSpecularity; clampIndex = ObjFile::Material::TextureSpecularityType; } else { - DefaultLogger::get()->error("OBJ/MTL: Encountered unknown texture type"); + ASSIMP_LOG_ERROR("OBJ/MTL: Encountered unknown texture type"); return; } diff --git a/code/ObjFileParser.cpp b/code/ObjFileParser.cpp index 004778259..7630127fa 100644 --- a/code/ObjFileParser.cpp +++ b/code/ObjFileParser.cpp @@ -426,7 +426,7 @@ void ObjFileParser::getFace( aiPrimitiveType type ) { if ( *m_DataIt =='/' ) { if (type == aiPrimitiveType_POINT) { - DefaultLogger::get()->error("Obj: Separator unexpected in point statement"); + ASSIMP_LOG_ERROR("Obj: Separator unexpected in point statement"); } if (iPos == 0) { //if there are no texture coordinates in the file, but normals @@ -486,7 +486,7 @@ void ObjFileParser::getFace( aiPrimitiveType type ) { } if ( face->m_vertices.empty() ) { - DefaultLogger::get()->error("Obj: Ignoring empty face"); + ASSIMP_LOG_ERROR("Obj: Ignoring empty face"); // skip line and clean up m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); delete face; @@ -556,7 +556,7 @@ void ObjFileParser::getMaterialDesc() { // This may be the case if the material library is missing. We don't want to lose all // materials if that happens, so create a new named material instead of discarding it // completely. - DefaultLogger::get()->error("OBJ: failed to locate material " + strName + ", creating new material"); + ASSIMP_LOG_ERROR("OBJ: failed to locate material " + strName + ", creating new material"); m_pModel->m_pCurrentMaterial = new ObjFile::Material(); m_pModel->m_pCurrentMaterial->MaterialName.Set(strName); m_pModel->m_MaterialLib.push_back(strName); @@ -620,12 +620,12 @@ void ObjFileParser::getMaterialLib() { IOStream *pFile = m_pIO->Open( absName ); if ( nullptr == pFile ) { - DefaultLogger::get()->error("OBJ: Unable to locate material file " + strMatName); + ASSIMP_LOG_ERROR("OBJ: Unable to locate material file " + strMatName); std::string strMatFallbackName = m_originalObjFileName.substr(0, m_originalObjFileName.length() - 3) + "mtl"; - DefaultLogger::get()->info("OBJ: Opening fallback material file " + strMatFallbackName); + ASSIMP_LOG_INFO("OBJ: Opening fallback material file " + strMatFallbackName); pFile = m_pIO->Open(strMatFallbackName); if (!pFile) { - DefaultLogger::get()->error("OBJ: Unable to locate fallback material file " + strMatFallbackName); + ASSIMP_LOG_ERROR("OBJ: Unable to locate fallback material file " + strMatFallbackName); m_DataIt = skipLine(m_DataIt, m_DataItEnd, m_uiLine); return; } @@ -817,7 +817,7 @@ void ObjFileParser::createMesh( const std::string &meshName ) } else { - DefaultLogger::get()->error("OBJ: No object detected to attach a new mesh instance."); + ASSIMP_LOG_ERROR("OBJ: No object detected to attach a new mesh instance."); } } @@ -851,7 +851,7 @@ bool ObjFileParser::needsNewMesh( const std::string &materialName ) void ObjFileParser::reportErrorTokenInFace() { m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); - DefaultLogger::get()->error("OBJ: Not supported token in face description detected"); + ASSIMP_LOG_ERROR("OBJ: Not supported token in face description detected"); } // ------------------------------------------------------------------- diff --git a/code/OgreBinarySerializer.cpp b/code/OgreBinarySerializer.cpp index 88fe02057..8948844d0 100644 --- a/code/OgreBinarySerializer.cpp +++ b/code/OgreBinarySerializer.cpp @@ -176,7 +176,7 @@ uint16_t OgreBinarySerializer::ReadHeader(bool readLen) #if (OGRE_BINARY_SERIALIZER_DEBUG == 1) if (id != HEADER_CHUNK_ID) { - DefaultLogger::get()->debug(Formatter::format() << (assetMode == AM_Mesh + ASSIMP_LOG_DEBUG(Formatter::format() << (assetMode == AM_Mesh ? MeshHeaderToString(static_cast(id)) : SkeletonHeaderToString(static_cast(id)))); } #endif @@ -192,7 +192,7 @@ void OgreBinarySerializer::RollbackHeader() void OgreBinarySerializer::SkipBytes(size_t numBytes) { #if (OGRE_BINARY_SERIALIZER_DEBUG == 1) - DefaultLogger::get()->debug(Formatter::format() << "Skipping " << numBytes << " bytes"); + ASSIMP_LOG_DEBUG_F( "Skipping ", numBytes, " bytes"); #endif m_reader->IncPtr(numBytes); @@ -237,8 +237,8 @@ void OgreBinarySerializer::ReadMesh(Mesh *mesh) { mesh->hasSkeletalAnimations = Read(); - DefaultLogger::get()->debug("Reading Mesh"); - DefaultLogger::get()->debug(Formatter::format() << " - Skeletal animations: " << (mesh->hasSkeletalAnimations ? "true" : "false")); + ASSIMP_LOG_DEBUG("Reading Mesh"); + ASSIMP_LOG_DEBUG_F( " - Skeletal animations: ", mesh->hasSkeletalAnimations ? "true" : "false" ); if (!AtEnd()) { @@ -420,9 +420,9 @@ void OgreBinarySerializer::ReadSubMesh(Mesh *mesh) submesh->indexData->faceCount = static_cast(submesh->indexData->count / 3); submesh->indexData->is32bit = Read(); - DefaultLogger::get()->debug(Formatter::format() << "Reading SubMesh " << mesh->subMeshes.size()); - DefaultLogger::get()->debug(Formatter::format() << " - Material: '" << submesh->materialRef << "'"); - DefaultLogger::get()->debug(Formatter::format() << " - Uses shared geometry: " << (submesh->usesSharedVertexData ? "true" : "false")); + ASSIMP_LOG_DEBUG_F( "Reading SubMesh ", mesh->subMeshes.size()); + ASSIMP_LOG_DEBUG_F( " - Material: '", submesh->materialRef, "'"); + ASSIMP_LOG_DEBUG_F( " - Uses shared geometry: ", submesh->usesSharedVertexData ? "true" : "false" ); // Index buffer if (submesh->indexData->count > 0) @@ -431,9 +431,9 @@ void OgreBinarySerializer::ReadSubMesh(Mesh *mesh) uint8_t *indexBuffer = ReadBytes(numBytes); submesh->indexData->buffer = MemoryStreamPtr(new Assimp::MemoryIOStream(indexBuffer, numBytes, true)); - DefaultLogger::get()->debug(Formatter::format() << " - " << submesh->indexData->faceCount - << " faces from " << submesh->indexData->count << (submesh->indexData->is32bit ? " 32bit" : " 16bit") - << " indexes of " << numBytes << " bytes"); + ASSIMP_LOG_DEBUG_F( " - ", submesh->indexData->faceCount, + " faces from ", submesh->indexData->count, (submesh->indexData->is32bit ? " 32bit" : " 16bit"), + " indexes of ", numBytes, " bytes"); } // Vertex buffer if not referencing the shared geometry @@ -549,7 +549,7 @@ void OgreBinarySerializer::ReadSubMeshNames(Mesh *mesh) } submesh->name = ReadLine(); - DefaultLogger::get()->debug(Formatter::format() << " - SubMesh " << submesh->index << " name '" << submesh->name << "'"); + ASSIMP_LOG_DEBUG_F( " - SubMesh ", submesh->index, " name '", submesh->name, "'"); if (!AtEnd()) id = ReadHeader(); @@ -563,7 +563,7 @@ void OgreBinarySerializer::ReadGeometry(VertexData *dest) { dest->count = Read(); - DefaultLogger::get()->debug(Formatter::format() << " - Reading geometry of " << dest->count << " vertices"); + ASSIMP_LOG_DEBUG_F( " - Reading geometry of ", dest->count, " vertices"); if (!AtEnd()) { @@ -620,8 +620,8 @@ void OgreBinarySerializer::ReadGeometryVertexElement(VertexData *dest) element.offset = Read(); element.index = Read(); - DefaultLogger::get()->debug(Formatter::format() << " - Vertex element " << element.SemanticToString() << " of type " - << element.TypeToString() << " index=" << element.index << " source=" << element.source); + ASSIMP_LOG_DEBUG_F( " - Vertex element ", element.SemanticToString(), " of type ", + element.TypeToString(), " index=", element.index, " source=", element.source); dest->vertexElements.push_back(element); } @@ -642,7 +642,7 @@ void OgreBinarySerializer::ReadGeometryVertexBuffer(VertexData *dest) uint8_t *vertexBuffer = ReadBytes(numBytes); dest->vertexBindings[bindIndex] = MemoryStreamPtr(new Assimp::MemoryIOStream(vertexBuffer, numBytes, true)); - DefaultLogger::get()->debug(Formatter::format() << " - Read vertex buffer for source " << bindIndex << " of " << numBytes << " bytes"); + ASSIMP_LOG_DEBUG_F( " - Read vertex buffer for source ", bindIndex, " of ", numBytes, " bytes"); } void OgreBinarySerializer::ReadEdgeList(Mesh * /*mesh*/) @@ -892,13 +892,13 @@ MemoryStreamReaderPtr OgreBinarySerializer::OpenReader(Assimp::IOSystem *pIOHand { if (!EndsWith(filename, ".skeleton", false)) { - DefaultLogger::get()->error("Imported Mesh is referencing to unsupported '" + filename + "' skeleton file."); + ASSIMP_LOG_ERROR_F("Imported Mesh is referencing to unsupported '", filename, "' skeleton file."); return MemoryStreamReaderPtr(); } if (!pIOHandler->Exists(filename)) { - DefaultLogger::get()->error("Failed to find skeleton file '" + filename + "' that is referenced by imported Mesh."); + ASSIMP_LOG_ERROR_F("Failed to find skeleton file '", filename, "' that is referenced by imported Mesh."); return MemoryStreamReaderPtr(); } @@ -925,7 +925,7 @@ void OgreBinarySerializer::ReadSkeleton(Skeleton *skeleton) << " Supported versions: " << SKELETON_VERSION_1_8 << " and " << SKELETON_VERSION_1_1); } - DefaultLogger::get()->debug("Reading Skeleton"); + ASSIMP_LOG_DEBUG("Reading Skeleton"); bool firstBone = true; bool firstAnim = true; @@ -944,7 +944,7 @@ void OgreBinarySerializer::ReadSkeleton(Skeleton *skeleton) { if (firstBone) { - DefaultLogger::get()->debug(" - Bones"); + ASSIMP_LOG_DEBUG(" - Bones"); firstBone = false; } @@ -960,7 +960,7 @@ void OgreBinarySerializer::ReadSkeleton(Skeleton *skeleton) { if (firstAnim) { - DefaultLogger::get()->debug(" - Animations"); + ASSIMP_LOG_DEBUG(" - Animations"); firstAnim = false; } @@ -1003,7 +1003,7 @@ void OgreBinarySerializer::ReadBone(Skeleton *skeleton) throw DeadlyImportError(Formatter::format() << "Ogre Skeleton bone indexes not contiguous. Error at bone index " << bone->id); } - DefaultLogger::get()->debug(Formatter::format() << " " << bone->id << " " << bone->name); + ASSIMP_LOG_DEBUG_F( " ", bone->id, " ", bone->name); skeleton->bones.push_back(bone); } @@ -1053,7 +1053,7 @@ void OgreBinarySerializer::ReadSkeletonAnimation(Skeleton *skeleton) skeleton->animations.push_back(anim); - DefaultLogger::get()->debug(Formatter::format() << " " << anim->name << " (" << anim->length << " sec, " << anim->tracks.size() << " tracks)"); + ASSIMP_LOG_DEBUG_F( " ", anim->name, " (", anim->length, " sec, ", anim->tracks.size(), " tracks)"); } void OgreBinarySerializer::ReadSkeletonAnimationTrack(Skeleton * /*skeleton*/, Animation *dest) diff --git a/code/OgreMaterial.cpp b/code/OgreMaterial.cpp index f0fb515d8..ceca04da1 100644 --- a/code/OgreMaterial.cpp +++ b/code/OgreMaterial.cpp @@ -175,18 +175,18 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste if (materialFile) { break; } - DefaultLogger::get()->debug(Formatter::format() << "Source file for material '" << materialName << "' " << potentialFiles[i] << " does not exist"); + ASSIMP_LOG_DEBUG_F( "Source file for material '", materialName, "' ", potentialFiles[i], " does not exist"); } if (!materialFile) { - DefaultLogger::get()->error(Formatter::format() << "Failed to find source file for material '" << materialName << "'"); + ASSIMP_LOG_ERROR_F( "Failed to find source file for material '", materialName, "'"); return 0; } std::unique_ptr stream(materialFile); if (stream->FileSize() == 0) { - ASSIMP_LOG_WARN(Formatter::format() << "Source file for material '" << materialName << "' is empty (size is 0 bytes)"); + ASSIMP_LOG_WARN_F( "Source file for material '", materialName, "' is empty (size is 0 bytes)"); return 0; } @@ -201,7 +201,7 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste ss << &data[0]; } - DefaultLogger::get()->debug("Reading material '" + materialName + "'"); + ASSIMP_LOG_DEBUG_F("Reading material '", materialName, "'"); aiMaterial *material = new aiMaterial(); m_textures.clear(); @@ -234,7 +234,6 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste ss >> linePart; if (linePart != materialName) { - //DefaultLogger::get()->debug(Formatter::format() << "Found material '" << linePart << "' that does not match at index " << ss.tellg()); ss >> linePart; continue; } @@ -242,11 +241,11 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste NextAfterNewLine(ss, linePart); if (linePart != partBlockStart) { - DefaultLogger::get()->error(Formatter::format() << "Invalid material: block start missing near index " << ss.tellg()); + ASSIMP_LOG_ERROR_F( "Invalid material: block start missing near index ", ss.tellg()); return material; } - DefaultLogger::get()->debug("material '" + materialName + "'"); + ASSIMP_LOG_DEBUG_F("material '", materialName, "'"); while(linePart != partBlockEnd) { @@ -350,11 +349,11 @@ bool OgreImporter::ReadTechnique(const std::string &techniqueName, stringstream if (linePart != partBlockStart) { - DefaultLogger::get()->error(Formatter::format() << "Invalid material: Technique block start missing near index " << ss.tellg()); + ASSIMP_LOG_ERROR_F( "Invalid material: Technique block start missing near index ", ss.tellg()); return false; } - DefaultLogger::get()->debug(" technique '" + techniqueName + "'"); + ASSIMP_LOG_DEBUG_F(" technique '", techniqueName, "'"); const string partPass = "pass"; @@ -386,11 +385,11 @@ bool OgreImporter::ReadPass(const std::string &passName, stringstream &ss, aiMat if (linePart != partBlockStart) { - DefaultLogger::get()->error(Formatter::format() << "Invalid material: Pass block start missing near index " << ss.tellg()); + ASSIMP_LOG_ERROR_F( "Invalid material: Pass block start missing near index ", ss.tellg()); return false; } - DefaultLogger::get()->debug(" pass '" + passName + "'"); + ASSIMP_LOG_DEBUG_F(" pass '", passName, "'"); const string partAmbient = "ambient"; const string partDiffuse = "diffuse"; @@ -417,7 +416,7 @@ bool OgreImporter::ReadPass(const std::string &passName, stringstream &ss, aiMat ss >> r >> g >> b; const aiColor3D color(r, g, b); - DefaultLogger::get()->debug(Formatter::format() << " " << linePart << " " << r << " " << g << " " << b); + ASSIMP_LOG_DEBUG_F( " ", linePart, " ", r, " ", g, " ", b); if (linePart == partAmbient) { @@ -452,11 +451,11 @@ bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstr if (linePart != partBlockStart) { - DefaultLogger::get()->error(Formatter::format() << "Invalid material: Texture unit block start missing near index " << ss.tellg()); + ASSIMP_LOG_ERROR_F( "Invalid material: Texture unit block start missing near index ", ss.tellg()); return false; } - DefaultLogger::get()->debug(" texture_unit '" + textureUnitName + "'"); + ASSIMP_LOG_DEBUG_F(" texture_unit '", textureUnitName, "'"); const string partTexture = "texture"; const string partTextCoordSet = "tex_coord_set"; @@ -491,7 +490,7 @@ bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstr if (posSuffix != string::npos && posUnderscore != string::npos && posSuffix > posUnderscore) { string identifier = Ogre::ToLower(textureRef.substr(posUnderscore, posSuffix - posUnderscore)); - DefaultLogger::get()->debug(Formatter::format() << "Detecting texture type from filename postfix '" << identifier << "'"); + ASSIMP_LOG_DEBUG_F( "Detecting texture type from filename postfix '", identifier, "'"); if (identifier == "_n" || identifier == "_nrm" || identifier == "_nrml" || identifier == "_normal" || identifier == "_normals" || identifier == "_normalmap") { @@ -581,8 +580,8 @@ bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstr unsigned int textureTypeIndex = m_textures[textureType]; m_textures[textureType]++; - DefaultLogger::get()->debug(Formatter::format() << " texture '" << textureRef << "' type " << textureType - << " index " << textureTypeIndex << " UV " << uvCoord); + ASSIMP_LOG_DEBUG_F( " texture '", textureRef, "' type ", textureType, + " index ", textureTypeIndex, " UV ", uvCoord); aiString assimpTextureRef(textureRef); material->AddProperty(&assimpTextureRef, AI_MATKEY_TEXTURE(textureType, textureTypeIndex)); diff --git a/code/OgreXmlSerializer.cpp b/code/OgreXmlSerializer.cpp index 12b2bcbd9..5805a528d 100644 --- a/code/OgreXmlSerializer.cpp +++ b/code/OgreXmlSerializer.cpp @@ -190,7 +190,7 @@ std::string &OgreXmlSerializer::NextNode() CurrentNodeName(true); #if (OGRE_XML_SERIALIZER_DEBUG == 1) - DefaultLogger::get()->debug("<" + m_currentNodeName + ">"); + ASSIMP_LOG_DEBUG"<" + m_currentNodeName + ">"); #endif return m_currentNodeName; } @@ -210,7 +210,7 @@ std::string OgreXmlSerializer::CurrentNodeName(bool forceRead) std::string &OgreXmlSerializer::SkipCurrentNode() { #if (OGRE_XML_SERIALIZER_DEBUG == 1) - DefaultLogger::get()->debug("Skipping node <" + m_currentNodeName + ">"); + ASSIMP_LOG_DEBUG("Skipping node <" + m_currentNodeName + ">"); #endif for(;;) { @@ -317,7 +317,7 @@ void OgreXmlSerializer::ReadMesh(MeshXml *mesh) { throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting "); } - DefaultLogger::get()->debug("Reading Mesh"); + ASSIMP_LOG_DEBUG("Reading Mesh"); NextNode(); @@ -351,7 +351,7 @@ void OgreXmlSerializer::ReadMesh(MeshXml *mesh) { else if (m_currentNodeName == nnSkeletonLink) { mesh->skeletonRef = ReadAttribute("name"); - DefaultLogger::get()->debug("Read skeleton link " + mesh->skeletonRef); + ASSIMP_LOG_DEBUG_F("Read skeleton link ", mesh->skeletonRef); NextNode(); } // Assimp incompatible/ignored nodes @@ -363,7 +363,7 @@ void OgreXmlSerializer::ReadMesh(MeshXml *mesh) { void OgreXmlSerializer::ReadGeometry(VertexDataXml *dest) { dest->count = ReadAttribute("vertexcount"); - DefaultLogger::get()->debug(Formatter::format() << " - Reading geometry of " << dest->count << " vertices"); + ASSIMP_LOG_DEBUG_F( " - Reading geometry of ", dest->count, " vertices"); NextNode(); while(m_currentNodeName == nnVertexBuffer) { @@ -385,22 +385,22 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest) if (positions) { - DefaultLogger::get()->debug(" - Contains positions"); + ASSIMP_LOG_DEBUG(" - Contains positions"); dest->positions.reserve(dest->count); } if (normals) { - DefaultLogger::get()->debug(" - Contains normals"); + ASSIMP_LOG_DEBUG(" - Contains normals"); dest->normals.reserve(dest->count); } if (tangents) { - DefaultLogger::get()->debug(" - Contains tangents"); + ASSIMP_LOG_DEBUG(" - Contains tangents"); dest->tangents.reserve(dest->count); } if (uvs > 0) { - DefaultLogger::get()->debug(Formatter::format() << " - Contains " << uvs << " texture coords"); + ASSIMP_LOG_DEBUG_F( " - Contains ", uvs, " texture coords"); dest->uvs.resize(uvs); for(size_t i=0, len=dest->uvs.size(); iuvs[i].reserve(dest->count); @@ -508,7 +508,7 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest) } } if (warn) { - DefaultLogger::get()->warn("Vertex buffer attribute read not implemented for element: " + m_currentNodeName); + ASSIMP_LOG_WARN_F("Vertex buffer attribute read not implemented for element: ", m_currentNodeName); } } @@ -554,9 +554,9 @@ void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh) submesh->usesSharedVertexData = ReadAttribute(anUseSharedVertices); } - DefaultLogger::get()->debug(Formatter::format() << "Reading SubMesh " << mesh->subMeshes.size()); - DefaultLogger::get()->debug(Formatter::format() << " - Material: '" << submesh->materialRef << "'"); - DefaultLogger::get()->debug(Formatter::format() << " - Uses shared geometry: " << (submesh->usesSharedVertexData ? "true" : "false")); + ASSIMP_LOG_DEBUG_F( "Reading SubMesh ", mesh->subMeshes.size()); + ASSIMP_LOG_DEBUG_F( " - Material: '", submesh->materialRef, "'"); + ASSIMP_LOG_DEBUG_F( " - Uses shared geometry: ", (submesh->usesSharedVertexData ? "true" : "false")); // TODO: maybe we have always just 1 faces and 1 geometry and always in this order. this loop will only work correct, when the order // of faces and geometry changed, and not if we have more than one of one @@ -587,7 +587,7 @@ void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh) /// @todo Support quads if Ogre even supports them in XML (I'm not sure but I doubt it) if (!quadWarned && HasAttribute(anV4)) { - DefaultLogger::get()->warn("Submesh has quads with , only triangles are supported at the moment!"); + ASSIMP_LOG_WARN("Submesh has quads with , only triangles are supported at the moment!"); quadWarned = true; } @@ -597,31 +597,25 @@ void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh) NextNode(); } - if (submesh->indexData->faces.size() == submesh->indexData->faceCount) - { - DefaultLogger::get()->debug(Formatter::format() << " - Faces " << submesh->indexData->faceCount); - } - else - { + if (submesh->indexData->faces.size() == submesh->indexData->faceCount) { + ASSIMP_LOG_DEBUG_F( " - Faces ", submesh->indexData->faceCount); + } else { throw DeadlyImportError(Formatter::format() << "Read only " << submesh->indexData->faces.size() << " faces when should have read " << submesh->indexData->faceCount); } - } - else if (m_currentNodeName == nnGeometry) - { + } else if (m_currentNodeName == nnGeometry) { if (submesh->usesSharedVertexData) { throw DeadlyImportError("Found in when use shared geometry is true. Invalid mesh file."); } submesh->vertexData = new VertexDataXml(); ReadGeometry(submesh->vertexData); - } - else if (m_currentNodeName == nnBoneAssignments) - { + } else if (m_currentNodeName == nnBoneAssignments) { ReadBoneAssignments(submesh->vertexData); } // Assimp incompatible/ignored nodes - else + else { SkipCurrentNode(); + } } submesh->index = static_cast(mesh->subMeshes.size()); @@ -676,7 +670,7 @@ void OgreXmlSerializer::ReadBoneAssignments(VertexDataXml *dest) } } - DefaultLogger::get()->debug(Formatter::format() << " - " << dest->boneAssignments.size() << " bone assignments"); + ASSIMP_LOG_DEBUG_F( " - ", dest->boneAssignments.size(), " bone assignments"); } // Skeleton @@ -731,13 +725,13 @@ XmlReaderPtr OgreXmlSerializer::OpenReader(Assimp::IOSystem *pIOHandler, const s { if (!EndsWith(filename, ".skeleton.xml", false)) { - DefaultLogger::get()->error("Imported Mesh is referencing to unsupported '" + filename + "' skeleton file."); + ASSIMP_LOG_ERROR_F("Imported Mesh is referencing to unsupported '", filename, "' skeleton file."); return XmlReaderPtr(); } if (!pIOHandler->Exists(filename)) { - DefaultLogger::get()->error("Failed to find skeleton file '" + filename + "' that is referenced by imported Mesh."); + ASSIMP_LOG_ERROR_F("Failed to find skeleton file '", filename, "' that is referenced by imported Mesh."); return XmlReaderPtr(); } @@ -760,7 +754,7 @@ void OgreXmlSerializer::ReadSkeleton(Skeleton *skeleton) throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting "); } - DefaultLogger::get()->debug("Reading Skeleton"); + ASSIMP_LOG_DEBUG("Reading Skeleton"); // Optional blend mode from root node if (HasAttribute("blendmode")) { @@ -793,7 +787,7 @@ void OgreXmlSerializer::ReadAnimations(Skeleton *skeleton) throw DeadlyImportError("Cannot read for a Skeleton without bones"); } - DefaultLogger::get()->debug(" - Animations"); + ASSIMP_LOG_DEBUG(" - Animations"); NextNode(); while(m_currentNodeName == nnAnimation) @@ -809,7 +803,7 @@ void OgreXmlSerializer::ReadAnimations(Skeleton *skeleton) ReadAnimationTracks(anim); skeleton->animations.push_back(anim); - DefaultLogger::get()->debug(Formatter::format() << " " << anim->name << " (" << anim->length << " sec, " << anim->tracks.size() << " tracks)"); + ASSIMP_LOG_DEBUG_F( " ", anim->name, " (", anim->length, " sec, ", anim->tracks.size(), " tracks)"); } } @@ -867,7 +861,7 @@ void OgreXmlSerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationT { axis.x = 1.0f; if (angle != 0) { - DefaultLogger::get()->warn("Found invalid a key frame with a zero rotation axis in animation: " + anim->name); + ASSIMP_LOG_WARN_F("Found invalid a key frame with a zero rotation axis in animation: ", anim->name); } } keyframe.rotation = aiQuaternion(axis, angle); @@ -925,7 +919,7 @@ static bool BoneCompare(Bone *a, Bone *b) void OgreXmlSerializer::ReadBones(Skeleton *skeleton) { - DefaultLogger::get()->debug(" - Bones"); + ASSIMP_LOG_DEBUG(" - Bones"); NextNode(); while(m_currentNodeName == nnBone) @@ -994,7 +988,7 @@ void OgreXmlSerializer::ReadBones(Skeleton *skeleton) for (size_t i=0, len=skeleton->bones.size(); ibones[i]; - DefaultLogger::get()->debug(Formatter::format() << " " << b->id << " " << b->name); + ASSIMP_LOG_DEBUG_F( " ", b->id, " ", b->name); if (b->id != static_cast(i)) { throw DeadlyImportError(Formatter::format() << "Bone ids are not in sequence starting from 0. Missing index " << i); diff --git a/code/OpenGEXImporter.cpp b/code/OpenGEXImporter.cpp index 652ba0f98..9966c1f34 100644 --- a/code/OpenGEXImporter.cpp +++ b/code/OpenGEXImporter.cpp @@ -708,7 +708,7 @@ void OpenGEXImporter::handleMeshNode( ODDLParser::DDLNode *node, aiScene *pScene } else if ( "quads" == propKey ) { m_currentMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; } else { - DefaultLogger::get()->warn( propKey + " is not supported primitive type." ); + ASSIMP_LOG_WARN_F( propKey, " is not supported primitive type." ); } } } @@ -1213,12 +1213,11 @@ void OpenGEXImporter::resolveReferences() { if ( nullptr != m_currentMesh ) { unsigned int matIdx = static_cast< unsigned int >( m_material2refMap[ name ] ); if ( m_currentMesh->mMaterialIndex != 0 ) { - DefaultLogger::get()->warn( "Override of material reference in current mesh by material reference." ); + ASSIMP_LOG_WARN( "Override of material reference in current mesh by material reference." ); } m_currentMesh->mMaterialIndex = matIdx; } else { - DefaultLogger::get()->warn( "Cannot resolve material reference, because no current mesh is there." ); - + ASSIMP_LOG_WARN( "Cannot resolve material reference, because no current mesh is there." ); } } } diff --git a/code/OptimizeGraph.cpp b/code/OptimizeGraph.cpp index 7835c3f01..59a764d5c 100644 --- a/code/OptimizeGraph.cpp +++ b/code/OptimizeGraph.cpp @@ -242,7 +242,7 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode* nd, std::list& no // ------------------------------------------------------------------------------------------------ // Execute the post-processing step on the given scene void OptimizeGraphProcess::Execute( aiScene* pScene) { - DefaultLogger::get()->debug("OptimizeGraphProcess begin"); + ASSIMP_LOG_DEBUG("OptimizeGraphProcess begin"); nodes_in = nodes_out = count_merged = 0; mScene = pScene; @@ -329,12 +329,10 @@ void OptimizeGraphProcess::Execute( aiScene* pScene) { pScene->mRootNode->mParent = NULL; if (!DefaultLogger::isNullLogger()) { if ( nodes_in != nodes_out) { - - char buf[512]; - ::ai_snprintf(buf,512,"OptimizeGraphProcess finished; Input nodes: %u, Output nodes: %u",nodes_in,nodes_out); - DefaultLogger::get()->info(buf); + ASSIMP_LOG_INFO_F("OptimizeGraphProcess finished; Input nodes: ", nodes_in, ", Output nodes: ", nodes_out); + } else { + ASSIMP_LOG_DEBUG("OptimizeGraphProcess finished"); } - else DefaultLogger::get()->debug("OptimizeGraphProcess finished"); } meshes.clear(); locked.clear(); diff --git a/code/OptimizeMeshes.cpp b/code/OptimizeMeshes.cpp index f586cc316..25575b049 100644 --- a/code/OptimizeMeshes.cpp +++ b/code/OptimizeMeshes.cpp @@ -107,11 +107,11 @@ void OptimizeMeshesProcess::Execute( aiScene* pScene) { const unsigned int num_old = pScene->mNumMeshes; if (num_old <= 1) { - DefaultLogger::get()->debug("Skipping OptimizeMeshesProcess"); + ASSIMP_LOG_DEBUG("Skipping OptimizeMeshesProcess"); return; } - DefaultLogger::get()->debug("OptimizeMeshesProcess begin"); + ASSIMP_LOG_DEBUG("OptimizeMeshesProcess begin"); mScene = pScene; // need to clear persistent members from previous runs @@ -151,11 +151,9 @@ void OptimizeMeshesProcess::Execute( aiScene* pScene) std::copy(output.begin(),output.end(),mScene->mMeshes); if (output.size() != num_old) { - char tmp[512]; - ::ai_snprintf(tmp,512,"OptimizeMeshesProcess finished. Input meshes: %u, Output meshes: %u",num_old,pScene->mNumMeshes); - DefaultLogger::get()->info(tmp); + ASSIMP_LOG_DEBUG_F("OptimizeMeshesProcess finished. Input meshes: ", num_old, ", Output meshes: ", pScene->mNumMeshes); } else { - DefaultLogger::get()->debug( "OptimizeMeshesProcess finished" ); + ASSIMP_LOG_DEBUG( "OptimizeMeshesProcess finished" ); } } diff --git a/code/PlyParser.cpp b/code/PlyParser.cpp index b6bd60f9f..b51b6ac71 100644 --- a/code/PlyParser.cpp +++ b/code/PlyParser.cpp @@ -97,7 +97,7 @@ PLY::EDataType PLY::Property::ParseDataType(std::vector &buffer) { } if (PLY::EDT_INVALID == eOut) { - DefaultLogger::get()->info("Found unknown data type in PLY file. This is OK"); + ASSIMP_LOG_INFO("Found unknown data type in PLY file. This is OK"); } return eOut; @@ -229,7 +229,7 @@ PLY::ESemantic PLY::Property::ParseSemantic(std::vector &buffer) { eOut = PLY::EST_ZNormal; } else { - DefaultLogger::get()->info("Found unknown property semantic in file. This is ok"); + ASSIMP_LOG_INFO("Found unknown property semantic in file. This is ok"); PLY::DOM::SkipLine(buffer); } return eOut; @@ -295,7 +295,7 @@ bool PLY::Property::ParseProperty(std::vector &buffer, PLY::Property* pOut if (PLY::EST_INVALID == pOut->Semantic) { - DefaultLogger::get()->info("Found unknown semantic in PLY file. This is OK"); + ASSIMP_LOG_INFO("Found unknown semantic in PLY file. This is OK"); std::string(&buffer[0], &buffer[0] + strlen(&buffer[0])); } @@ -514,7 +514,7 @@ bool PLY::DOM::SkipComments(std::vector &buffer) // ------------------------------------------------------------------------------------------------ bool PLY::DOM::ParseHeader(IOStreamBuffer &streamBuffer, std::vector &buffer, bool isBinary) { - DefaultLogger::get()->debug("PLY::DOM::ParseHeader() begin"); + ASSIMP_LOG_DEBUG("PLY::DOM::ParseHeader() begin"); // parse all elements while (!buffer.empty()) @@ -543,14 +543,14 @@ bool PLY::DOM::ParseHeader(IOStreamBuffer &streamBuffer, std::vector if (!isBinary) // it would occur an error, if binary data start with values as space or line end. SkipSpacesAndLineEnd(buffer); - DefaultLogger::get()->debug("PLY::DOM::ParseHeader() succeeded"); + ASSIMP_LOG_DEBUG("PLY::DOM::ParseHeader() succeeded"); return true; } // ------------------------------------------------------------------------------------------------ bool PLY::DOM::ParseElementInstanceLists(IOStreamBuffer &streamBuffer, std::vector &buffer, PLYImporter* loader) { - DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() begin"); + ASSIMP_LOG_DEBUG("PLY::DOM::ParseElementInstanceLists() begin"); alElementData.resize(alElements.size()); std::vector::const_iterator i = alElements.begin(); @@ -571,7 +571,7 @@ bool PLY::DOM::ParseElementInstanceLists(IOStreamBuffer &streamBuffer, std } } - DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() succeeded"); + ASSIMP_LOG_DEBUG("PLY::DOM::ParseElementInstanceLists() succeeded"); return true; } @@ -582,7 +582,7 @@ bool PLY::DOM::ParseElementInstanceListsBinary(IOStreamBuffer &streamBuffe PLYImporter* loader, bool p_bBE) { - DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() begin"); + ASSIMP_LOG_DEBUG("PLY::DOM::ParseElementInstanceListsBinary() begin"); alElementData.resize(alElements.size()); std::vector::const_iterator i = alElements.begin(); @@ -602,7 +602,7 @@ bool PLY::DOM::ParseElementInstanceListsBinary(IOStreamBuffer &streamBuffe } } - DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() succeeded"); + ASSIMP_LOG_DEBUG("PLY::DOM::ParseElementInstanceListsBinary() succeeded"); return true; } @@ -615,11 +615,11 @@ bool PLY::DOM::ParseInstanceBinary(IOStreamBuffer &streamBuffer, DOM* p_pc std::vector buffer; streamBuffer.getNextLine(buffer); - DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() begin"); + ASSIMP_LOG_DEBUG("PLY::DOM::ParseInstanceBinary() begin"); if (!p_pcOut->ParseHeader(streamBuffer, buffer, true)) { - DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure"); + ASSIMP_LOG_DEBUG("PLY::DOM::ParseInstanceBinary() failure"); return false; } @@ -628,10 +628,10 @@ bool PLY::DOM::ParseInstanceBinary(IOStreamBuffer &streamBuffer, DOM* p_pc const char* pCur = (char*)&buffer[0]; if (!p_pcOut->ParseElementInstanceListsBinary(streamBuffer, buffer, pCur, bufferSize, loader, p_bBE)) { - DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure"); + ASSIMP_LOG_DEBUG("PLY::DOM::ParseInstanceBinary() failure"); return false; } - DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() succeeded"); + ASSIMP_LOG_DEBUG("PLY::DOM::ParseInstanceBinary() succeeded"); return true; } @@ -644,11 +644,11 @@ bool PLY::DOM::ParseInstance(IOStreamBuffer &streamBuffer, DOM* p_pcOut, P std::vector buffer; streamBuffer.getNextLine(buffer); - DefaultLogger::get()->debug("PLY::DOM::ParseInstance() begin"); + ASSIMP_LOG_DEBUG("PLY::DOM::ParseInstance() begin"); if (!p_pcOut->ParseHeader(streamBuffer, buffer, false)) { - DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure"); + ASSIMP_LOG_DEBUG("PLY::DOM::ParseInstance() failure"); return false; } @@ -656,10 +656,10 @@ bool PLY::DOM::ParseInstance(IOStreamBuffer &streamBuffer, DOM* p_pcOut, P streamBuffer.getNextLine(buffer); if (!p_pcOut->ParseElementInstanceLists(streamBuffer, buffer, loader)) { - DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure"); + ASSIMP_LOG_DEBUG("PLY::DOM::ParseInstance() failure"); return false; } - DefaultLogger::get()->debug("PLY::DOM::ParseInstance() succeeded"); + ASSIMP_LOG_DEBUG("PLY::DOM::ParseInstance() succeeded"); return true; } diff --git a/code/PretransformVertices.cpp b/code/PretransformVertices.cpp index cc5c669e4..0623f00ef 100644 --- a/code/PretransformVertices.cpp +++ b/code/PretransformVertices.cpp @@ -391,7 +391,7 @@ void PretransformVertices::BuildWCSMeshes(std::vector& out, aiMesh** in } if (node->mMeshes[i] < numIn) { // Worst case. Need to operate on a full copy of the mesh - DefaultLogger::get()->info("PretransformVertices: Copying mesh due to mismatching transforms"); + ASSIMP_LOG_INFO("PretransformVertices: Copying mesh due to mismatching transforms"); aiMesh* ntz; const unsigned int tmp = mesh->mNumBones; // @@ -441,7 +441,7 @@ void PretransformVertices::BuildMeshRefCountArray(aiNode* nd, unsigned int * ref // Executes the post processing step on the given imported data. void PretransformVertices::Execute( aiScene* pScene) { - DefaultLogger::get()->debug("PretransformVerticesProcess begin"); + ASSIMP_LOG_DEBUG("PretransformVerticesProcess begin"); // Return immediately if we have no meshes if (!pScene->mNumMeshes) @@ -713,22 +713,12 @@ void PretransformVertices::Execute( aiScene* pScene) } // print statistics - if (!DefaultLogger::isNullLogger()) - { - char buffer[4096]; + if (!DefaultLogger::isNullLogger()) { + ASSIMP_LOG_DEBUG("PretransformVerticesProcess finished"); - DefaultLogger::get()->debug("PretransformVerticesProcess finished"); - - ::ai_snprintf(buffer,4096,"Removed %u nodes and %u animation channels (%u output nodes)", - iOldNodes,iOldAnimationChannels,CountNodes(pScene->mRootNode)); - DefaultLogger::get()->info(buffer); - - ai_snprintf(buffer, 4096,"Kept %u lights and %u cameras", - pScene->mNumLights,pScene->mNumCameras); - DefaultLogger::get()->info(buffer); - - ai_snprintf(buffer, 4096,"Moved %u meshes to WCS (number of output meshes: %u)", - iOldMeshes,pScene->mNumMeshes); - DefaultLogger::get()->info(buffer); + ASSIMP_LOG_INFO_F("Removed ", iOldNodes, " nodes and ", iOldAnimationChannels, " animation channels (", + CountNodes(pScene->mRootNode) ," output nodes)" ); + ASSIMP_LOG_INFO_F("Kept ", pScene->mNumLights, " lights and ", pScene->mNumCameras, " cameras." ); + ASSIMP_LOG_INFO_F("Moved ", iOldMeshes, " meshes to WCS (number of output meshes: ", pScene->mNumMeshes, ")"); } } diff --git a/code/ProcessHelper.cpp b/code/ProcessHelper.cpp index d6f8cd165..7f3e4ba72 100644 --- a/code/ProcessHelper.cpp +++ b/code/ProcessHelper.cpp @@ -62,7 +62,7 @@ void ConvertListToStrings(const std::string& in, std::list& out) while (*s != '\'') { ++s; if (*s == '\0') { - DefaultLogger::get()->error("ConvertListToString: String list is ill-formatted"); + ASSIMP_LOG_ERROR("ConvertListToString: String list is ill-formatted"); return; } } diff --git a/code/ProcessHelper.h b/code/ProcessHelper.h index 5ef3707e8..c668b946f 100644 --- a/code/ProcessHelper.h +++ b/code/ProcessHelper.h @@ -348,7 +348,7 @@ class ComputeSpatialSortProcess : public BaseProcess void Execute( aiScene* pScene) { typedef std::pair _Type; - DefaultLogger::get()->debug("Generate spatially-sorted vertex cache"); + ASSIMP_LOG_DEBUG("Generate spatially-sorted vertex cache"); std::vector<_Type>* p = new std::vector<_Type>(pScene->mNumMeshes); std::vector<_Type>::iterator it = p->begin(); diff --git a/code/Q3DLoader.cpp b/code/Q3DLoader.cpp index ebb80d537..f1165dc2c 100644 --- a/code/Q3DLoader.cpp +++ b/code/Q3DLoader.cpp @@ -125,7 +125,7 @@ void Q3DImporter::InternReadFile( const std::string& pFile, } // Print the file format version - DefaultLogger::get()->info("Quick3D File format version: " + + ASSIMP_LOG_INFO_F("Quick3D File format version: ", std::string(&((const char*)stream.GetPtr())[8],2)); // ... an store it @@ -413,7 +413,7 @@ outer: // If we have no materials loaded - generate a default mat if (materials.empty()) { - DefaultLogger::get()->info("Quick3D: No material found, generating one"); + ASSIMP_LOG_INFO("Quick3D: No material found, generating one"); materials.push_back(Material()); materials.back().diffuse = fgColor ; } diff --git a/code/RawLoader.cpp b/code/RawLoader.cpp index 0c149a1f6..1bc508759 100644 --- a/code/RawLoader.cpp +++ b/code/RawLoader.cpp @@ -160,7 +160,7 @@ void RAWImporter::InternReadFile( const std::string& pFile, } if (num != 12 && num != 9) { - DefaultLogger::get()->error("A line may have either 9 or 12 floats and an optional texture"); + ASSIMP_LOG_ERROR("A line may have either 9 or 12 floats and an optional texture"); continue; } diff --git a/code/RemoveRedundantMaterials.cpp b/code/RemoveRedundantMaterials.cpp index 683fb7fdd..7194d3c8e 100644 --- a/code/RemoveRedundantMaterials.cpp +++ b/code/RemoveRedundantMaterials.cpp @@ -87,7 +87,7 @@ void RemoveRedundantMatsProcess::SetupProperties(const Importer* pImp) // Executes the post processing step on the given imported data. void RemoveRedundantMatsProcess::Execute( aiScene* pScene) { - DefaultLogger::get()->debug("RemoveRedundantMatsProcess begin"); + ASSIMP_LOG_DEBUG("RemoveRedundantMatsProcess begin"); unsigned int redundantRemoved = 0, unreferencedRemoved = 0; if (pScene->mNumMaterials) @@ -122,7 +122,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) // Keep this material even if no mesh references it abReferenced[i] = true; - DefaultLogger::get()->debug(std::string("Found positive match in exclusion list: \'") + name.data + "\'"); + ASSIMP_LOG_DEBUG_F( "Found positive match in exclusion list: \'", name.data, "\'"); } } } @@ -211,13 +211,11 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) } if (redundantRemoved == 0 && unreferencedRemoved == 0) { - DefaultLogger::get()->debug("RemoveRedundantMatsProcess finished "); + ASSIMP_LOG_DEBUG("RemoveRedundantMatsProcess finished "); } else { - char szBuffer[128]; // should be sufficiently large - ::ai_snprintf(szBuffer,128,"RemoveRedundantMatsProcess finished. Removed %u redundant and %u unused materials.", - redundantRemoved,unreferencedRemoved); - DefaultLogger::get()->info(szBuffer); + ASSIMP_LOG_INFO_F("RemoveRedundantMatsProcess finished. Removed ", redundantRemoved, " redundant and ", + unreferencedRemoved, " unused materials."); } } diff --git a/code/RemoveVCProcess.cpp b/code/RemoveVCProcess.cpp index ddb0023cc..81249eab2 100644 --- a/code/RemoveVCProcess.cpp +++ b/code/RemoveVCProcess.cpp @@ -145,7 +145,7 @@ bool UpdateNodeGraph(aiNode* node,std::list& childsOfParent,bool root) // Executes the post processing step on the given imported data. void RemoveVCProcess::Execute( aiScene* pScene) { - DefaultLogger::get()->debug("RemoveVCProcess begin"); + ASSIMP_LOG_DEBUG("RemoveVCProcess begin"); bool bHas = false; //,bMasked = false; mScene = pScene; @@ -224,15 +224,18 @@ void RemoveVCProcess::Execute( aiScene* pScene) if (!pScene->mNumMeshes || !pScene->mNumMaterials) { pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; - DefaultLogger::get()->debug("Setting AI_SCENE_FLAGS_INCOMPLETE flag"); + ASSIMP_LOG_DEBUG("Setting AI_SCENE_FLAGS_INCOMPLETE flag"); // If we have no meshes anymore we should also clear another flag ... if (!pScene->mNumMeshes) pScene->mFlags &= ~AI_SCENE_FLAGS_NON_VERBOSE_FORMAT; } - if (bHas)DefaultLogger::get()->info("RemoveVCProcess finished. Data structure cleanup has been done."); - else DefaultLogger::get()->debug("RemoveVCProcess finished. Nothing to be done ..."); + if (bHas) { + ASSIMP_LOG_INFO("RemoveVCProcess finished. Data structure cleanup has been done."); + } else { + ASSIMP_LOG_DEBUG("RemoveVCProcess finished. Nothing to be done ..."); + } } // ------------------------------------------------------------------------------------------------ diff --git a/code/SIBImporter.cpp b/code/SIBImporter.cpp index 5c8c717b5..7a69dd175 100644 --- a/code/SIBImporter.cpp +++ b/code/SIBImporter.cpp @@ -150,7 +150,7 @@ static SIBChunk ReadChunk(StreamReaderLE* stream) chunk.Tag = stream->GetU4(); chunk.Size = stream->GetU4(); if (chunk.Size > stream->GetRemainingSizeToLimit()) - DefaultLogger::get()->error("SIB: Chunk overflow"); + ASSIMP_LOG_ERROR("SIB: Chunk overflow"); ByteSwap::Swap4(&chunk.Tag); return chunk; } @@ -589,7 +589,7 @@ static void ReadShape(SIB* sib, StreamReaderLE* stream) if (mtl >= meshes.size()) { - DefaultLogger::get()->error("SIB: Face material index is invalid."); + ASSIMP_LOG_ERROR("SIB: Face material index is invalid."); mtl = 0; } diff --git a/code/SMDLoader.cpp b/code/SMDLoader.cpp index 4f9ed5c1c..dc6706934 100644 --- a/code/SMDLoader.cpp +++ b/code/SMDLoader.cpp @@ -286,7 +286,7 @@ void SMDImporter::CreateOutputMeshes() if (UINT_MAX == (*iFace).iTexture)aaiFaces[(*iFace).iTexture].push_back( 0 ); else if ((*iFace).iTexture >= aszTextures.size()) { - DefaultLogger::get()->error("[SMD/VTA] Material index overflow in face"); + ASSIMP_LOG_INFO("[SMD/VTA] Material index overflow in face"); aaiFaces[(*iFace).iTexture].push_back((unsigned int)aszTextures.size()-1); } else aaiFaces[(*iFace).iTexture].push_back(iNum); @@ -366,7 +366,7 @@ void SMDImporter::CreateOutputMeshes() if (pairval.first >= asBones.size() || pairval.first == face.avVertices[iVert].iParentNode) { - DefaultLogger::get()->error("[SMD/VTA] Bone index overflow. " + ASSIMP_LOG_ERROR("[SMD/VTA] Bone index overflow. " "The bone index will be ignored, the weight will be assigned " "to the vertex' parent node"); continue; @@ -387,7 +387,7 @@ void SMDImporter::CreateOutputMeshes() { if (face.avVertices[iVert].iParentNode >= asBones.size()) { - DefaultLogger::get()->error("[SMD/VTA] Bone index overflow. " + ASSIMP_LOG_ERROR("[SMD/VTA] Bone index overflow. " "The index of the vertex parent bone is invalid. " "The remaining weights will be normalized to 1.0"); @@ -953,7 +953,7 @@ void SMDImporter::ParseSkeletonElement(const char* szCurrent, unsigned int iBone = 0; if(!ParseUnsignedInt(szCurrent,&szCurrent,iBone)) { - DefaultLogger::get()->error("Unexpected EOF/EOL while parsing bone index"); + ASSIMP_LOG_ERROR("Unexpected EOF/EOL while parsing bone index"); SMDI_PARSE_RETURN; } if (iBone >= asBones.size()) diff --git a/code/STEPFile.h b/code/STEPFile.h index d789faac2..492150658 100644 --- a/code/STEPFile.h +++ b/code/STEPFile.h @@ -776,10 +776,10 @@ namespace STEP { // XXX is this really how the EXPRESS notation ([?:3],[1:3]) is intended? if (max_cnt && inp->GetSize() > max_cnt) { - DefaultLogger::get()->warn("too many aggregate elements"); + ASSIMP_LOG_WARN("too many aggregate elements"); } else if (inp->GetSize() < min_cnt) { - DefaultLogger::get()->warn("too few aggregate elements"); + ASSIMP_LOG_WARN("too few aggregate elements"); } out.reserve(inp->GetSize()); diff --git a/code/STLLoader.cpp b/code/STLLoader.cpp index 3a85a5495..46808503d 100644 --- a/code/STLLoader.cpp +++ b/code/STLLoader.cpp @@ -286,14 +286,14 @@ void STLImporter::LoadASCIIFile( aiNode *root ) { if(!SkipSpacesAndLineEnd(&sz)) { // seems we're finished although there was no end marker - DefaultLogger::get()->warn("STL: unexpected EOF. \'endsolid\' keyword was expected"); + ASSIMP_LOG_WARN("STL: unexpected EOF. \'endsolid\' keyword was expected"); break; } // facet normal -0.13 -0.13 -0.98 if (!strncmp(sz,"facet",5) && IsSpaceOrNewLine(*(sz+5)) && *(sz + 5) != '\0') { if (faceVertexCounter != 3) { - DefaultLogger::get()->warn("STL: A new facet begins but the old is not yet complete"); + ASSIMP_LOG_WARN("STL: A new facet begins but the old is not yet complete"); } faceVertexCounter = 0; normalBuffer.push_back(aiVector3D()); @@ -302,7 +302,7 @@ void STLImporter::LoadASCIIFile( aiNode *root ) { sz += 6; SkipSpaces(&sz); if (strncmp(sz,"normal",6)) { - DefaultLogger::get()->warn("STL: a facet normal vector was expected but not found"); + ASSIMP_LOG_WARN("STL: a facet normal vector was expected but not found"); } else { if (sz[6] == '\0') { throw DeadlyImportError("STL: unexpected EOF while parsing facet"); @@ -319,7 +319,7 @@ void STLImporter::LoadASCIIFile( aiNode *root ) { } } else if (!strncmp(sz,"vertex",6) && ::IsSpaceOrNewLine(*(sz+6))) { // vertex 1.50000 1.50000 0.00000 if (faceVertexCounter >= 3) { - DefaultLogger::get()->error("STL: a facet with more than 3 vertices has been found"); + ASSIMP_LOG_ERROR("STL: a facet with more than 3 vertices has been found"); ++sz; } else { if (sz[6] == '\0') { @@ -418,7 +418,7 @@ bool STLImporter::LoadBinaryFile() // read the default vertex color for facets bIsMaterialise = true; - DefaultLogger::get()->info("STL: Taking code path for Materialise files"); + ASSIMP_LOG_INFO("STL: Taking code path for Materialise files"); const ai_real invByte = (ai_real)1.0 / ( ai_real )255.0; clrColorDefault.r = (*sz2++) * invByte; clrColorDefault.g = (*sz2++) * invByte; @@ -500,7 +500,7 @@ bool STLImporter::LoadBinaryFile() *pMesh->mColors[0]++ = this->clrColorDefault; pMesh->mColors[0] -= pMesh->mNumVertices; - DefaultLogger::get()->info("STL: Mesh has vertex colors"); + ASSIMP_LOG_INFO("STL: Mesh has vertex colors"); } aiColor4D* clr = &pMesh->mColors[0][i*3]; clr->a = 1.0; diff --git a/code/SortByPTypeProcess.cpp b/code/SortByPTypeProcess.cpp index 8d6be695d..ee18585e2 100644 --- a/code/SortByPTypeProcess.cpp +++ b/code/SortByPTypeProcess.cpp @@ -137,11 +137,11 @@ void SortByPTypeProcess::Execute( aiScene* pScene) { if (!pScene->mNumMeshes) { - DefaultLogger::get()->debug("SortByPTypeProcess skipped, there are no meshes"); + ASSIMP_LOG_DEBUG("SortByPTypeProcess skipped, there are no meshes"); return; } - DefaultLogger::get()->debug("SortByPTypeProcess begin"); + ASSIMP_LOG_DEBUG("SortByPTypeProcess begin"); unsigned int aiNumMeshesPerPType[4] = {0,0,0,0}; @@ -404,8 +404,8 @@ void SortByPTypeProcess::Execute( aiScene* pScene) aiNumMeshesPerPType[1], ((configRemoveMeshes & aiPrimitiveType_LINE) ? "X" : ""), aiNumMeshesPerPType[2], ((configRemoveMeshes & aiPrimitiveType_TRIANGLE) ? "X" : ""), aiNumMeshesPerPType[3], ((configRemoveMeshes & aiPrimitiveType_POLYGON) ? "X" : "")); - DefaultLogger::get()->info(buffer); - DefaultLogger::get()->debug("SortByPTypeProcess finished"); + ASSIMP_LOG_INFO(buffer); + ASSIMP_LOG_DEBUG("SortByPTypeProcess finished"); } } diff --git a/code/SplitLargeMeshes.cpp b/code/SplitLargeMeshes.cpp index f24ddd205..28b655fa4 100644 --- a/code/SplitLargeMeshes.cpp +++ b/code/SplitLargeMeshes.cpp @@ -78,7 +78,7 @@ void SplitLargeMeshesProcess_Triangle::Execute( aiScene* pScene) { if (0xffffffff == this->LIMIT)return; - DefaultLogger::get()->debug("SplitLargeMeshesProcess_Triangle begin"); + ASSIMP_LOG_DEBUG("SplitLargeMeshesProcess_Triangle begin"); std::vector > avList; for( unsigned int a = 0; a < pScene->mNumMeshes; a++) @@ -96,10 +96,11 @@ void SplitLargeMeshesProcess_Triangle::Execute( aiScene* pScene) // now we need to update all nodes this->UpdateNode(pScene->mRootNode,avList); - DefaultLogger::get()->info("SplitLargeMeshesProcess_Triangle finished. Meshes have been split"); + ASSIMP_LOG_INFO("SplitLargeMeshesProcess_Triangle finished. Meshes have been split"); + } + else { + ASSIMP_LOG_DEBUG("SplitLargeMeshesProcess_Triangle finished. There was nothing to do"); } - else DefaultLogger::get()->debug("SplitLargeMeshesProcess_Triangle finished. There was nothing to do"); - return; } // ------------------------------------------------------------------------------------------------ @@ -154,7 +155,7 @@ void SplitLargeMeshesProcess_Triangle::SplitMesh( { if (pMesh->mNumFaces > SplitLargeMeshesProcess_Triangle::LIMIT) { - DefaultLogger::get()->info("Mesh exceeds the triangle limit. It will be split ..."); + ASSIMP_LOG_INFO("Mesh exceeds the triangle limit. It will be split ..."); // we need to split this mesh into sub meshes // determine the size of a submesh @@ -378,7 +379,7 @@ void SplitLargeMeshesProcess_Vertex::Execute( aiScene* pScene) if (0xffffffff == this->LIMIT)return; - DefaultLogger::get()->debug("SplitLargeMeshesProcess_Vertex begin"); + ASSIMP_LOG_DEBUG("SplitLargeMeshesProcess_Vertex begin"); for( unsigned int a = 0; a < pScene->mNumMeshes; a++) this->SplitMesh(a, pScene->mMeshes[a],avList); @@ -394,10 +395,10 @@ void SplitLargeMeshesProcess_Vertex::Execute( aiScene* pScene) // now we need to update all nodes SplitLargeMeshesProcess_Triangle::UpdateNode(pScene->mRootNode,avList); - DefaultLogger::get()->info("SplitLargeMeshesProcess_Vertex finished. Meshes have been split"); + ASSIMP_LOG_INFO("SplitLargeMeshesProcess_Vertex finished. Meshes have been split"); + } else { + ASSIMP_LOG_DEBUG("SplitLargeMeshesProcess_Vertex finished. There was nothing to do"); } - else DefaultLogger::get()->debug("SplitLargeMeshesProcess_Vertex finished. There was nothing to do"); - return; } // ------------------------------------------------------------------------------------------------ diff --git a/code/Subdivision.cpp b/code/Subdivision.cpp index ced560764..2f2f09596 100644 --- a/code/Subdivision.cpp +++ b/code/Subdivision.cpp @@ -342,11 +342,8 @@ void CatmullClarkSubdivider::InternSubdivide ( // Report the number of bad edges. bad edges are referenced by less than two // faces in the mesh. They occur at outer model boundaries in non-closed // shapes. - char tmp[512]; - ai_snprintf(tmp, 512, "Catmull-Clark Subdivider: got %u bad edges touching only one face (totally %u edges). ", - bad_cnt,static_cast(edges.size())); - - DASSIMP_LOG_DEBUG(tmp); + ASSIMP_LOG_DEBUG_F("Catmull-Clark Subdivider: got ", bad_cnt, " bad edges touching only one face (totally ", + static_cast(edges.size()), " edges). "); }} // --------------------------------------------------------------------- diff --git a/code/TerragenLoader.cpp b/code/TerragenLoader.cpp index 0f5f4cb9d..0eb22cef6 100644 --- a/code/TerragenLoader.cpp +++ b/code/TerragenLoader.cpp @@ -192,7 +192,7 @@ void TerragenImporter::InternReadFile( const std::string& pFile, { mode = reader.GetI1(); if (0 != mode) - DefaultLogger::get()->error("TER: Unsupported mapping mode, a flat terrain is returned"); + ASSIMP_LOG_ERROR("TER: Unsupported mapping mode, a flat terrain is returned"); } // actual terrain data else if (!::strncmp(head,AI_TERR_CHUNK_ALTW,4)) diff --git a/code/TextureTransform.cpp b/code/TextureTransform.cpp index 62bbadd08..a21835b13 100644 --- a/code/TextureTransform.cpp +++ b/code/TextureTransform.cpp @@ -105,12 +105,10 @@ void TextureTransformStep::PreProcessUVTransform(STransformVecInfo& info) if (info.mRotation) { float out = info.mRotation; - if ((rounded = (int)(info.mRotation / (float)AI_MATH_TWO_PI))) + if ((rounded = static_cast((info.mRotation / static_cast(AI_MATH_TWO_PI))))) { - out -= rounded*(float)AI_MATH_PI; - - ai_snprintf(szTemp, 512, "Texture coordinate rotation %f can be simplified to %f",info.mRotation,out); - DefaultLogger::get()->info(szTemp); + out -= rounded * static_cast(AI_MATH_PI); + ASSIMP_LOG_INFO_F("Texture coordinate rotation ", info.mRotation, " can be simplified to ", out); } // Next step - convert negative rotation angles to positives @@ -150,7 +148,7 @@ void TextureTransformStep::PreProcessUVTransform(STransformVecInfo& info) out = 1.f; } if (szTemp[0]) { - DefaultLogger::get()->info(szTemp); + ASSIMP_LOG_INFO(szTemp); info.mTranslation.x = out; } } @@ -183,7 +181,7 @@ void TextureTransformStep::PreProcessUVTransform(STransformVecInfo& info) out = 1.f; } if (szTemp[0]) { - DefaultLogger::get()->info(szTemp); + ASSIMP_LOG_INFO(szTemp); info.mTranslation.y = out; } } @@ -221,7 +219,7 @@ inline const char* MappingModeToChar(aiTextureMapMode map) // ------------------------------------------------------------------------------------------------ void TextureTransformStep::Execute( aiScene* pScene) { - DefaultLogger::get()->debug("TransformUVCoordsProcess begin"); + ASSIMP_LOG_DEBUG("TransformUVCoordsProcess begin"); /* We build a per-mesh list of texture transformations we'll need @@ -416,7 +414,7 @@ void TextureTransformStep::Execute( aiScene* pScene) ++it2; if ((*it2).lockedPos != AI_TT_UV_IDX_LOCK_NONE) { - DefaultLogger::get()->error("Channel mismatch, can't compute all transformations properly [design bug]"); + ASSIMP_LOG_ERROR("Channel mismatch, can't compute all transformations properly [design bug]"); continue; } @@ -449,10 +447,8 @@ void TextureTransformStep::Execute( aiScene* pScene) if (size > AI_MAX_NUMBER_OF_TEXTURECOORDS) { if (!DefaultLogger::isNullLogger()) { - ::ai_snprintf(buffer,1024,"%u UV channels required but just %u available", - static_cast(trafo.size()),AI_MAX_NUMBER_OF_TEXTURECOORDS); - - DefaultLogger::get()->error(buffer); + ASSIMP_LOG_ERROR_F(static_cast(trafo.size()), " UV channels required but just ", + AI_MAX_NUMBER_OF_TEXTURECOORDS, " available"); } size = AI_MAX_NUMBER_OF_TEXTURECOORDS; } @@ -487,7 +483,7 @@ void TextureTransformStep::Execute( aiScene* pScene) MappingModeToChar ((*it).mapU), MappingModeToChar ((*it).mapV)); - DefaultLogger::get()->info(buffer); + ASSIMP_LOG_INFO(buffer); } // Check whether we need a new buffer here @@ -560,12 +556,10 @@ void TextureTransformStep::Execute( aiScene* pScene) if (!DefaultLogger::isNullLogger()) { if (transformedChannels) { - ::ai_snprintf(buffer,1024,"TransformUVCoordsProcess end: %u output channels (in: %u, modified: %u)", - outChannels,inChannels,transformedChannels); - - DefaultLogger::get()->info(buffer); + ASSIMP_LOG_INFO_F("TransformUVCoordsProcess end: ", outChannels, " output channels (in: ", inChannels, ", modified: ", transformedChannels,")"); + } else { + ASSIMP_LOG_DEBUG("TransformUVCoordsProcess finished"); } - else DefaultLogger::get()->debug("TransformUVCoordsProcess finished"); } } diff --git a/code/TriangulateProcess.cpp b/code/TriangulateProcess.cpp index 25d92c470..cc8b05c47 100644 --- a/code/TriangulateProcess.cpp +++ b/code/TriangulateProcess.cpp @@ -100,7 +100,7 @@ bool TriangulateProcess::IsActive( unsigned int pFlags) const // Executes the post processing step on the given imported data. void TriangulateProcess::Execute( aiScene* pScene) { - DefaultLogger::get()->debug("TriangulateProcess begin"); + ASSIMP_LOG_DEBUG("TriangulateProcess begin"); bool bHas = false; for( unsigned int a = 0; a < pScene->mNumMeshes; a++) @@ -110,13 +110,12 @@ void TriangulateProcess::Execute( aiScene* pScene) } } if ( bHas ) { - DefaultLogger::get()->info( "TriangulateProcess finished. All polygons have been triangulated." ); + ASSIMP_LOG_INFO( "TriangulateProcess finished. All polygons have been triangulated." ); } else { - DefaultLogger::get()->debug( "TriangulateProcess finished. There was nothing to be done." ); + ASSIMP_LOG_DEBUG( "TriangulateProcess finished. There was nothing to be done." ); } } - // ------------------------------------------------------------------------------------------------ // Triangulates the given mesh. bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) @@ -410,7 +409,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) // Instead we're continuing with the standard tri-fanning algorithm which we'd // use if we had only convex polygons. That's life. - DefaultLogger::get()->error("Failed to triangulate polygon (no ear found). Probably not a simple polygon?"); + ASSIMP_LOG_ERROR("Failed to triangulate polygon (no ear found). Probably not a simple polygon?"); #ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS fprintf(fout,"critical error here, no ear found! "); @@ -488,7 +487,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) // drop dumb 0-area triangles if (std::fabs(GetArea2D(temp_verts[i[0]],temp_verts[i[1]],temp_verts[i[2]])) < 1e-5f) { - DefaultLogger::get()->debug("Dropping triangle with area 0"); + ASSIMP_LOG_DEBUG("Dropping triangle with area 0"); --curOut; delete[] f->mIndices; diff --git a/code/ValidateDataStructure.cpp b/code/ValidateDataStructure.cpp index 20b348763..51e04b96b 100644 --- a/code/ValidateDataStructure.cpp +++ b/code/ValidateDataStructure.cpp @@ -206,7 +206,7 @@ inline void ValidateDSProcess::DoValidationWithNameCheck(T** array, void ValidateDSProcess::Execute( aiScene* pScene) { this->mScene = pScene; - DefaultLogger::get()->debug("ValidateDataStructureProcess begin"); + ASSIMP_LOG_DEBUG("ValidateDataStructureProcess begin"); // validate the node graph of the scene Validate(pScene->mRootNode); @@ -273,7 +273,7 @@ void ValidateDSProcess::Execute( aiScene* pScene) } // if (!has)ReportError("The aiScene data structure is empty"); - DefaultLogger::get()->debug("ValidateDataStructureProcess end"); + ASSIMP_LOG_DEBUG("ValidateDataStructureProcess end"); } // ------------------------------------------------------------------------------------------------ diff --git a/code/XFileImporter.cpp b/code/XFileImporter.cpp index fd28fbb79..94b38e303 100644 --- a/code/XFileImporter.cpp +++ b/code/XFileImporter.cpp @@ -587,7 +587,7 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, std::vectorwarn( format() << "Could not resolve global material reference \"" << oldMat.mName << "\"" ); + ASSIMP_LOG_WARN_F( "Could not resolve global material reference \"", oldMat.mName, "\"" ); oldMat.sceneIndex = 0; } diff --git a/code/XFileParser.cpp b/code/XFileParser.cpp index 4dd2c990b..0988edaff 100644 --- a/code/XFileParser.cpp +++ b/code/XFileParser.cpp @@ -255,7 +255,7 @@ XFileParser::XFileParser( const std::vector& pBuffer) // FIXME: we don't need the compressed data anymore, could release // it already for better memory usage. Consider breaking const-co. - DefaultLogger::get()->info("Successfully decompressed MSZIP-compressed file"); + ASSIMP_LOG_INFO("Successfully decompressed MSZIP-compressed file"); #endif // !! ASSIMP_BUILD_NO_COMPRESSED_X } else @@ -322,11 +322,11 @@ void XFileParser::ParseFile() if( objectName == "}") { // whatever? - DefaultLogger::get()->warn("} found in dataObject"); + ASSIMP_LOG_WARN("} found in dataObject"); } else { // unknown format - DefaultLogger::get()->warn("Unknown data object in animation of .x file"); + ASSIMP_LOG_WARN("Unknown data object in animation of .x file"); ParseUnknownDataObject(); } } @@ -422,7 +422,7 @@ void XFileParser::ParseDataObjectFrame( Node* pParent) ParseDataObjectMesh( mesh); } else { - DefaultLogger::get()->warn("Unknown data object in frame in x file"); + ASSIMP_LOG_WARN("Unknown data object in frame in x file"); ParseUnknownDataObject(); } } @@ -509,7 +509,7 @@ void XFileParser::ParseDataObjectMesh( Mesh* pMesh) ParseDataObjectSkinWeights( pMesh); else { - DefaultLogger::get()->warn("Unknown data object in mesh in x file"); + ASSIMP_LOG_WARN("Unknown data object in mesh in x file"); ParseUnknownDataObject(); } } @@ -719,7 +719,7 @@ void XFileParser::ParseDataObjectMeshMaterialList( Mesh* pMesh) // ignore } else { - DefaultLogger::get()->warn("Unknown data object in material list in x file"); + ASSIMP_LOG_WARN("Unknown data object in material list in x file"); ParseUnknownDataObject(); } } @@ -767,7 +767,7 @@ void XFileParser::ParseDataObjectMaterial( Material* pMaterial) pMaterial->mTextures.push_back( TexEntry( texname, true)); } else { - DefaultLogger::get()->warn("Unknown data object in material in x file"); + ASSIMP_LOG_WARN("Unknown data object in material in x file"); ParseUnknownDataObject(); } } @@ -805,7 +805,7 @@ void XFileParser::ParseDataObjectAnimationSet() ParseDataObjectAnimation( anim); else { - DefaultLogger::get()->warn("Unknown data object in animation set in x file"); + ASSIMP_LOG_WARN("Unknown data object in animation set in x file"); ParseUnknownDataObject(); } } @@ -842,7 +842,7 @@ void XFileParser::ParseDataObjectAnimation( Animation* pAnim) CheckForClosingBrace(); } else { - DefaultLogger::get()->warn("Unknown data object in animation in x file"); + ASSIMP_LOG_WARN("Unknown data object in animation in x file"); ParseUnknownDataObject(); } } @@ -950,7 +950,7 @@ void XFileParser::ParseDataObjectTextureFilename( std::string& pName) // FIX: some files (e.g. AnimationTest.x) have "" as texture file name if (!pName.length()) { - DefaultLogger::get()->warn("Length of texture file name is zero. Skipping this texture."); + ASSIMP_LOG_WARN("Length of texture file name is zero. Skipping this texture."); } // some exporters write double backslash paths out. We simply replace them if we find them diff --git a/include/assimp/LogAux.h b/include/assimp/LogAux.h index b8aa2e2d2..cf6d50014 100644 --- a/include/assimp/LogAux.h +++ b/include/assimp/LogAux.h @@ -64,28 +64,28 @@ public: // ------------------------------------------------------------------------------------------------ static void LogWarn(const Formatter::format& message) { if (!DefaultLogger::isNullLogger()) { - DefaultLogger::get()->warn(Prefix()+(std::string)message); + ASSIMP_LOG_WARN(Prefix()+(std::string)message); } } // ------------------------------------------------------------------------------------------------ static void LogError(const Formatter::format& message) { if (!DefaultLogger::isNullLogger()) { - DefaultLogger::get()->error(Prefix()+(std::string)message); + ASSIMP_LOG_ERROR(Prefix()+(std::string)message); } } // ------------------------------------------------------------------------------------------------ static void LogInfo(const Formatter::format& message) { if (!DefaultLogger::isNullLogger()) { - DefaultLogger::get()->info(Prefix()+(std::string)message); + ASSIMP_LOG_INFO(Prefix()+(std::string)message); } } // ------------------------------------------------------------------------------------------------ static void LogDebug(const Formatter::format& message) { if (!DefaultLogger::isNullLogger()) { - DefaultLogger::get()->debug(Prefix()+(std::string)message); + ASSIMP_LOG_DEBUG(Prefix()+(std::string)message); } } @@ -126,6 +126,6 @@ private: static const char* Prefix(); }; - } // ! Assimp + #endif From dd7d0943f6bfd4502b0285518917f3a8093a931b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 26 Apr 2018 14:24:00 +0200 Subject: [PATCH 166/278] Update glTF2Asset.inl Move creation of vars to avoid useless creation in case of an error. --- code/glTF2Asset.inl | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index e132765ff..d96db6d74 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -461,36 +461,38 @@ inline void Buffer::EncodedRegion_SetCurrent(const std::string& pID) throw DeadlyImportError("GLTF: EncodedRegion with ID: \"" + pID + "\" not found."); } -inline bool Buffer::ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count) +inline +bool Buffer::ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count) { -const size_t new_data_size = byteLength + pReplace_Count - pBufferData_Count; -uint8_t* new_data; + if((pBufferData_Count == 0) || (pReplace_Count == 0) || (pReplace_Data == nullptr)) { + return false; + } - if((pBufferData_Count == 0) || (pReplace_Count == 0) || (pReplace_Data == nullptr)) return false; - - new_data = new uint8_t[new_data_size]; + const size_t new_data_size = byteLength + pReplace_Count - pBufferData_Count; + uint8_t *new_data = new uint8_t[new_data_size]; // Copy data which place before replacing part. - memcpy(new_data, mData.get(), pBufferData_Offset); + ::memcpy(new_data, mData.get(), pBufferData_Offset); // Copy new data. - memcpy(&new_data[pBufferData_Offset], pReplace_Data, pReplace_Count); + ::memcpy(&new_data[pBufferData_Offset], pReplace_Data, pReplace_Count); // Copy data which place after replacing part. - memcpy(&new_data[pBufferData_Offset + pReplace_Count], &mData.get()[pBufferData_Offset + pBufferData_Count], pBufferData_Offset); + ::memcpy(&new_data[pBufferData_Offset + pReplace_Count], &mData.get()[pBufferData_Offset + pBufferData_Count], pBufferData_Offset); // Apply new data mData.reset(new_data, std::default_delete()); byteLength = new_data_size; return true; } -inline bool Buffer::ReplaceData_joint(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count) + +inline +bool Buffer::ReplaceData_joint(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count) { -const size_t new_data_size = byteLength + pReplace_Count - pBufferData_Count; + if((pBufferData_Count == 0) || (pReplace_Count == 0) || (pReplace_Data == nullptr)) { + return false; + } -uint8_t* new_data; - - if((pBufferData_Count == 0) || (pReplace_Count == 0) || (pReplace_Data == nullptr)) return false; - - new_data = new uint8_t[new_data_size]; + const size_t new_data_size = byteLength + pReplace_Count - pBufferData_Count; + uint8_t* new_data = new uint8_t[new_data_size]; // Copy data which place before replacing part. memcpy(new_data, mData.get(), pBufferData_Offset); // Copy new data. From 3d79472172c9e4bacbfdb0a54fb2b034bc552247 Mon Sep 17 00:00:00 2001 From: kimkulling Date: Thu, 26 Apr 2018 14:36:59 +0200 Subject: [PATCH 167/278] fix the build. --- code/BaseImporter.cpp | 2 +- code/DefaultIOSystem.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/BaseImporter.cpp b/code/BaseImporter.cpp index fa9f70603..78979d078 100644 --- a/code/BaseImporter.cpp +++ b/code/BaseImporter.cpp @@ -595,7 +595,7 @@ void BatchLoader::LoadAll() if (!DefaultLogger::isNullLogger()) { ASSIMP_LOG_INFO("%%% BEGIN EXTERNAL FILE %%%"); - ASSIMP_LOG_INFO("File: ", (*it).file); + ASSIMP_LOG_INFO_F("File: ", (*it).file); } m_data->pImporter->ReadFile((*it).file,pp); (*it).scene = m_data->pImporter->GetOrphanedScene(); diff --git a/code/DefaultIOSystem.cpp b/code/DefaultIOSystem.cpp index ec0de6e3a..3afaf69e0 100644 --- a/code/DefaultIOSystem.cpp +++ b/code/DefaultIOSystem.cpp @@ -189,7 +189,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out) if(!ret) { // preserve the input path, maybe someone else is able to fix // the path before it is accessed (e.g. our file system filter) - ASSIMP_LOG_WARN("Invalid path: ", std::string(in)); + ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in)); strcpy(_out,in); } #endif From 75c7b15b5541cc5c2c94b32c249d083d0a335a1b Mon Sep 17 00:00:00 2001 From: kimkulling Date: Thu, 26 Apr 2018 15:05:49 +0200 Subject: [PATCH 168/278] Fix c++11 usage. --- code/MDLMaterialLoader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/MDLMaterialLoader.cpp b/code/MDLMaterialLoader.cpp index e80d3b560..2c21b188b 100644 --- a/code/MDLMaterialLoader.cpp +++ b/code/MDLMaterialLoader.cpp @@ -75,7 +75,7 @@ void MDLImporter::SearchPalette(const unsigned char** pszColorMap) { if (pcStream->FileSize() >= 768) { - constexpr size_t len = 256 * 3; + size_t len = 256 * 3; unsigned char* colorMap = new unsigned char[len]; szColorMap = colorMap; pcStream->Read(colorMap, len,1); From a5e14db19b0bfbaa59bd7ad6ded65ab7acb3dd8d Mon Sep 17 00:00:00 2001 From: kimkulling Date: Thu, 26 Apr 2018 15:41:31 +0200 Subject: [PATCH 169/278] fix invaid macro usage. --- code/DXFLoader.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/code/DXFLoader.cpp b/code/DXFLoader.cpp index 7d8b6eca2..c77d13a7e 100644 --- a/code/DXFLoader.cpp +++ b/code/DXFLoader.cpp @@ -373,7 +373,7 @@ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& bloc // first check if the referenced blocks exists ... const DXF::BlockMap::const_iterator it = blocks_by_name.find(insert.name); if (it == blocks_by_name.end()) { - ASSIMP_LOG_ERROR("DXF: Failed to resolve block reference: ", insert.name,"; skipping" ); + ASSIMP_LOG_ERROR_F("DXF: Failed to resolve block reference: ", insert.name,"; skipping" ); continue; } @@ -406,7 +406,6 @@ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& bloc } } - // ------------------------------------------------------------------------------------------------ void DXFImporter::GenerateMaterials(aiScene* pScene, DXF::FileData& /*output*/) { @@ -433,7 +432,6 @@ void DXFImporter::GenerateMaterials(aiScene* pScene, DXF::FileData& /*output*/) pScene->mMaterials[0] = pcMat; } - // ------------------------------------------------------------------------------------------------ void DXFImporter::GenerateHierarchy(aiScene* pScene, DXF::FileData& /*output*/) { @@ -444,9 +442,7 @@ void DXFImporter::GenerateHierarchy(aiScene* pScene, DXF::FileData& /*output*/) if (1 == pScene->mNumMeshes) { pScene->mRootNode->mMeshes = new unsigned int[ pScene->mRootNode->mNumMeshes = 1 ]; pScene->mRootNode->mMeshes[0] = 0; - } - else - { + } else { pScene->mRootNode->mChildren = new aiNode*[ pScene->mRootNode->mNumChildren = pScene->mNumMeshes ]; for (unsigned int m = 0; m < pScene->mRootNode->mNumChildren;++m) { aiNode* p = pScene->mRootNode->mChildren[m] = new aiNode(); From c299755721f06d93d6305b6ad10514b362ed1a0c Mon Sep 17 00:00:00 2001 From: kimkulling Date: Thu, 26 Apr 2018 16:13:57 +0200 Subject: [PATCH 170/278] DXF: fix macro issues. --- code/DXFLoader.cpp | 36 ++++++++++-------------------------- 1 file changed, 10 insertions(+), 26 deletions(-) diff --git a/code/DXFLoader.cpp b/code/DXFLoader.cpp index c77d13a7e..90270bbd7 100644 --- a/code/DXFLoader.cpp +++ b/code/DXFLoader.cpp @@ -241,7 +241,7 @@ void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output) } } - ASSIMP_LOG_DEBUG("DXF: Unexpanded polycount is ", icount, ", vertex count is ", vcount); + ASSIMP_LOG_DEBUG_F("DXF: Unexpanded polycount is ", icount, ", vertex count is ", vcount); } if (! output.blocks.size() ) { @@ -457,22 +457,17 @@ void DXFImporter::GenerateHierarchy(aiScene* pScene, DXF::FileData& /*output*/) // ------------------------------------------------------------------------------------------------ -void DXFImporter::SkipSection(DXF::LineReader& reader) -{ +void DXFImporter::SkipSection(DXF::LineReader& reader) { for( ;!reader.End() && !reader.Is(0,"ENDSEC"); reader++); } - // ------------------------------------------------------------------------------------------------ -void DXFImporter::ParseHeader(DXF::LineReader& reader, DXF::FileData& /*output*/) -{ +void DXFImporter::ParseHeader(DXF::LineReader& reader, DXF::FileData& ) { for( ;!reader.End() && !reader.Is(0,"ENDSEC"); reader++); } - // ------------------------------------------------------------------------------------------------ -void DXFImporter::ParseBlocks(DXF::LineReader& reader, DXF::FileData& output) -{ +void DXFImporter::ParseBlocks(DXF::LineReader& reader, DXF::FileData& output) { while( !reader.End() && !reader.Is(0,"ENDSEC")) { if (reader.Is(0,"BLOCK")) { ParseBlock(++reader,output); @@ -481,15 +476,11 @@ void DXFImporter::ParseBlocks(DXF::LineReader& reader, DXF::FileData& output) ++reader; } - ASSIMP_LOG_DEBUG((Formatter::format("DXF: got "), - output.blocks.size()," entries in BLOCKS" - )); + ASSIMP_LOG_DEBUG_F("DXF: got ", output.blocks.size()," entries in BLOCKS" ); } - // ------------------------------------------------------------------------------------------------ -void DXFImporter::ParseBlock(DXF::LineReader& reader, DXF::FileData& output) -{ +void DXFImporter::ParseBlock(DXF::LineReader& reader, DXF::FileData& output) { // push a new block onto the stack. output.blocks.push_back( DXF::Block() ); DXF::Block& block = output.blocks.back(); @@ -533,7 +524,6 @@ void DXFImporter::ParseBlock(DXF::LineReader& reader, DXF::FileData& output) } } - // ------------------------------------------------------------------------------------------------ void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output) { @@ -563,19 +553,16 @@ void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output) ++reader; } - ASSIMP_LOG_DEBUG((Formatter::format("DXF: got "), - block.lines.size()," polylines and ", block.insertions.size() ," inserted blocks in ENTITIES" - )); + ASSIMP_LOG_DEBUG_F( "DXF: got ", block.lines.size()," polylines and ", block.insertions.size(), + " inserted blocks in ENTITIES" ); } - void DXFImporter::ParseInsertion(DXF::LineReader& reader, DXF::FileData& output) { output.blocks.back().insertions.push_back( DXF::InsertBlock() ); DXF::InsertBlock& bl = output.blocks.back().insertions.back(); while( !reader.End() && !reader.Is(0)) { - switch(reader.GroupCode()) { // name of referenced block @@ -620,8 +607,7 @@ void DXFImporter::ParseInsertion(DXF::LineReader& reader, DXF::FileData& output) #define DXF_POLYLINE_FLAG_POLYFACEMESH 0x40 // ------------------------------------------------------------------------------------------------ -void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output) -{ +void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output) { output.blocks.back().lines.push_back( std::shared_ptr( new DXF::PolyLine() ) ); DXF::PolyLine& line = *output.blocks.back().lines.back(); @@ -788,8 +774,7 @@ void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& li } line.indices.push_back(indices[i]-1); } - } - else { + } else { line.positions.push_back(out); line.colors.push_back(clr); } @@ -915,4 +900,3 @@ void DXFImporter::Parse3DFace(DXF::LineReader& reader, DXF::FileData& output) } #endif // !! ASSIMP_BUILD_NO_DXF_IMPORTER - From 8626b185fbe38a8a539addf90cbb3a8b1b9d4c16 Mon Sep 17 00:00:00 2001 From: kimkulling Date: Thu, 26 Apr 2018 16:38:42 +0200 Subject: [PATCH 171/278] Fix misused log macros + compiler warnings. --- code/ColladaLoader.cpp | 30 +++++++++++++++--------------- code/DefaultIOSystem.cpp | 2 +- code/FBXExporter.cpp | 8 ++++---- code/MD3Loader.cpp | 2 +- tools/assimp_view/assimp_view.rc | 2 +- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/code/ColladaLoader.cpp b/code/ColladaLoader.cpp index a26df1898..45dd52710 100644 --- a/code/ColladaLoader.cpp +++ b/code/ColladaLoader.cpp @@ -472,7 +472,7 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll if( !srcMesh) { - ASSIMP_LOG_WARN( "Collada: Unable to find geometry for ID \"", mid.mMeshOrController, "\". Skipping." ); + ASSIMP_LOG_WARN_F( "Collada: Unable to find geometry for ID \"", mid.mMeshOrController, "\". Skipping." ); continue; } } else @@ -875,7 +875,7 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada:: if( bnode) bone->mName.Set( FindNameForNode( bnode)); else - ASSIMP_LOG_WARN( "ColladaLoader::CreateMesh(): could not find corresponding node for joint \"", bone->mName.data, "\"." ); + ASSIMP_LOG_WARN_F( "ColladaLoader::CreateMesh(): could not find corresponding node for joint \"", bone->mName.data, "\"." ); // and insert bone dstMesh->mBones[boneCount++] = bone; @@ -1176,9 +1176,8 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars else if( subElement == "Z") entry.mSubElement = 2; else - ASSIMP_LOG_WARN( "Unknown anim subelement <", subElement, ">. Ignoring" ); - } else - { + ASSIMP_LOG_WARN_F( "Unknown anim subelement <", subElement, ">. Ignoring" ); + } else { // no subelement following, transformId is remaining string entry.mTransformId = srcChannel.mTarget.substr( slashPos+1); } @@ -1658,9 +1657,10 @@ void ColladaLoader::FillMaterials( const ColladaParser& pParser, aiScene* /*pSce } // add textures, if given - if( !effect.mTexAmbient.mName.empty()) - /* It is merely a lightmap */ - AddTexture( mat, pParser, effect, effect.mTexAmbient, aiTextureType_LIGHTMAP); + if (!effect.mTexAmbient.mName.empty()) { + // It is merely a light-map + AddTexture(mat, pParser, effect, effect.mTexAmbient, aiTextureType_LIGHTMAP); + } if( !effect.mTexEmissive.mName.empty()) AddTexture( mat, pParser, effect, effect.mTexEmissive, aiTextureType_EMISSIVE); @@ -1688,8 +1688,8 @@ void ColladaLoader::BuildMaterials( ColladaParser& pParser, aiScene* /*pScene*/) { newMats.reserve(pParser.mMaterialLibrary.size()); - for( ColladaParser::MaterialLibrary::const_iterator matIt = pParser.mMaterialLibrary.begin(); matIt != pParser.mMaterialLibrary.end(); ++matIt) - { + for( ColladaParser::MaterialLibrary::const_iterator matIt = pParser.mMaterialLibrary.begin(); + matIt != pParser.mMaterialLibrary.end(); ++matIt) { const Collada::Material& material = matIt->second; // a material is only a reference to an effect ColladaParser::EffectLibrary::iterator effIt = pParser.mEffectLibrary.find( material.mEffect); @@ -1808,7 +1808,7 @@ void ColladaLoader::ConvertPath (aiString& ss) { // TODO: collada spec, p 22. Handle URI correctly. // For the moment we're just stripping the file:// away to make it work. - // Windoes doesn't seem to be able to find stuff like + // Windows doesn't seem to be able to find stuff like // 'file://..\LWO\LWO2\MappingModes\earthSpherical.jpg' if (0 == strncmp(ss.data,"file://",7)) { @@ -1822,7 +1822,7 @@ void ColladaLoader::ConvertPath (aiString& ss) if( ss.data[0] == '/' && isalpha( ss.data[1]) && ss.data[2] == ':' ) { ss.length--; - memmove( ss.data, ss.data+1, ss.length); + ::memmove( ss.data, ss.data+1, ss.length); ss.data[ss.length] = 0; } @@ -1872,9 +1872,9 @@ const std::string& ColladaLoader::ReadString( const Collada::Accessor& pAccessor void ColladaLoader::CollectNodes( const aiNode* pNode, std::vector& poNodes) const { poNodes.push_back( pNode); - - for( size_t a = 0; a < pNode->mNumChildren; ++a) - CollectNodes( pNode->mChildren[a], poNodes); + for (size_t a = 0; a < pNode->mNumChildren; ++a) { + CollectNodes(pNode->mChildren[a], poNodes); + } } // ------------------------------------------------------------------------------------------------ diff --git a/code/DefaultIOSystem.cpp b/code/DefaultIOSystem.cpp index 3afaf69e0..fee9c3e7f 100644 --- a/code/DefaultIOSystem.cpp +++ b/code/DefaultIOSystem.cpp @@ -179,7 +179,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out) if (!ret) { // preserve the input path, maybe someone else is able to fix // the path before it is accessed (e.g. our file system filter) - ASSIMP_LOG_WARN("Invalid path: ", std::string(in)); + ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in)); strcpy(_out, in); } } diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index 4945ec5dc..52c69161a 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -71,7 +71,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // https://code.blender.org/2013/08/fbx-binary-file-format-specification/ // https://wiki.blender.org/index.php/User:Mont29/Foundation/FBX_File_Structure -const double DEG = 57.29577951308232087679815481; // degrees per radian +const ai_real DEG = ai_real( 57.29577951308232087679815481 ); // degrees per radian // some constants that we'll use for writing metadata namespace FBX { @@ -980,9 +980,9 @@ aiMatrix4x4 get_world_transform(const aiNode* node, const aiScene* scene) int64_t to_ktime(double ticks, const aiAnimation* anim) { if (anim->mTicksPerSecond <= 0) { - return ticks * FBX::SECOND; + return static_cast(ticks) * FBX::SECOND; } - return (ticks / anim->mTicksPerSecond) * FBX::SECOND; + return (static_cast(ticks) / static_cast(anim->mTicksPerSecond)) * FBX::SECOND; } void FBXExporter::WriteObjects () @@ -2440,7 +2440,7 @@ void FBXExporter::WriteAnimationCurve( // TODO: keyattr flags and data (STUB for now) n.AddChild("KeyAttrFlags", std::vector{0}); n.AddChild("KeyAttrDataFloat", std::vector{0,0,0,0}); - ai_assert(times.size() <= std::numeric_limits::max()); + ai_assert(static_cast(times.size()) <= std::numeric_limits::max()); n.AddChild( "KeyAttrRefCount", std::vector{static_cast(times.size())} diff --git a/code/MD3Loader.cpp b/code/MD3Loader.cpp index 4e0b24acb..d12f2d5fd 100644 --- a/code/MD3Loader.cpp +++ b/code/MD3Loader.cpp @@ -1037,7 +1037,7 @@ void MD3Importer::InternReadFile( const std::string& pFile, if (!DefaultLogger::isNullLogger()) { for (std::list< Q3Shader::SkinData::TextureEntry>::const_iterator it = skins.textures.begin();it != skins.textures.end(); ++it) { if (!(*it).resolved) { - ASSIMP_LOG_ERROR("MD3: Failed to match skin ", (*it).first, " to surface ", (*it).second); + ASSIMP_LOG_ERROR_F("MD3: Failed to match skin ", (*it).first, " to surface ", (*it).second); } } } diff --git a/tools/assimp_view/assimp_view.rc b/tools/assimp_view/assimp_view.rc index aebb1e2d9..093b860fc 100644 --- a/tools/assimp_view/assimp_view.rc +++ b/tools/assimp_view/assimp_view.rc @@ -189,7 +189,7 @@ BEGIN LTEXT "Angle limit (in degrees):",IDC_STATIC,13,10,76,8 LTEXT "The angle limit defines the maximum angle that may be between two adjacent face normals that they're smoothed together.",IDC_STATIC,13,31,253,19 CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,113,278,1 - LTEXT "This setting is also used during import, but it can be overridden by single model importers to match the original look of a model as closely as possible. Examples include 3DS, ASE and LWO, all of them relying on smoothing groups and their own angle limits. ",IDC_STATIC,13,51,254,33 + LTEXT "Also used during import, but can be overridden by single model importers to match the original look of a model as close as possible. Examples includes 3DS, ASE and LWO, all of them relying on smoothing groups and their own angle limits. ",IDC_STATIC,13,51,254,33 LTEXT "NOTE: New settings don't take effect immediately, use 'Smooth Normals' or 'Reload' to update the model.",IDC_STATIC,14,118,254,22 CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,90,277,1 END From 6a311210e77aa285079463f72d9dfca726a70c11 Mon Sep 17 00:00:00 2001 From: kimkulling Date: Thu, 26 Apr 2018 17:01:22 +0200 Subject: [PATCH 172/278] fix another bug of misusage of the log macros. --- code/COBLoader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/COBLoader.cpp b/code/COBLoader.cpp index 1d4ee2464..d6692f7d2 100644 --- a/code/COBLoader.cpp +++ b/code/COBLoader.cpp @@ -837,7 +837,7 @@ void COBImporter::ReadBitM_Ascii(Scene& /*out*/, LineSplitter& splitter, const C const unsigned int head = strtoul10((++splitter)[1]); if (head != sizeof(Bitmap::BitmapHeader)) { - ASSIMP_LOG_WARN_F("Unexpected ThumbNailHdrSize, skipping this chunk"); + ASSIMP_LOG_WARN("Unexpected ThumbNailHdrSize, skipping this chunk"); return; } From b877b3e10ea5533496b82ff0db7ef42255b05714 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 26 Apr 2018 22:01:41 +0200 Subject: [PATCH 173/278] use correct log macro. --- code/COBLoader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/COBLoader.cpp b/code/COBLoader.cpp index d6692f7d2..a9784fbec 100644 --- a/code/COBLoader.cpp +++ b/code/COBLoader.cpp @@ -777,7 +777,7 @@ void COBImporter::ReadPolH_Ascii(Scene& out, LineSplitter& splitter, const Chunk for(unsigned int cur = 0; cur < cnt && ++splitter ;++cur) { if (splitter.match_start("Hole")) { - ASSIMP_LOG_WARN_F( "Skipping unsupported `Hole` line" ); + ASSIMP_LOG_WARN( "Skipping unsupported `Hole` line" ); continue; } From 1f9d6f1ec4b60ce94699ac4f644d472d45e8e71e Mon Sep 17 00:00:00 2001 From: Sebastian Matusik Date: Thu, 26 Apr 2018 17:34:27 +0100 Subject: [PATCH 174/278] Fix for blendshapes import when using the JoinIdenticalVertices optimization flag --- code/JoinVerticesProcess.cpp | 277 ++++++++++++++++++++--------------- include/assimp/Vertex.h | 24 +++ 2 files changed, 179 insertions(+), 122 deletions(-) diff --git a/code/JoinVerticesProcess.cpp b/code/JoinVerticesProcess.cpp index cffe74fb2..cb2d4c1f5 100644 --- a/code/JoinVerticesProcess.cpp +++ b/code/JoinVerticesProcess.cpp @@ -114,6 +114,125 @@ void JoinVerticesProcess::Execute( aiScene* pScene) pScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT; } +namespace { + +bool areVerticesEqual(const Vertex &lhs, const Vertex &rhs, bool complex) +{ + // A little helper to find locally close vertices faster. + // Try to reuse the lookup table from the last step. + const static float epsilon = 1e-5f; + // Squared because we check against squared length of the vector difference + static const float squareEpsilon = epsilon * epsilon; + + // Square compare is useful for animeshes vertexes compare + if ((lhs.position - rhs.position).SquareLength() > squareEpsilon) { + return false; + } + + // We just test the other attributes even if they're not present in the mesh. + // In this case they're initialized to 0 so the comparison succeeds. + // By this method the non-present attributes are effectively ignored in the comparison. + if ((lhs.normal - rhs.normal).SquareLength() > squareEpsilon) { + return false; + } + + if ((lhs.texcoords[0] - rhs.texcoords[0]).SquareLength() > squareEpsilon) { + return false; + } + + if ((lhs.tangent - rhs.tangent).SquareLength() > squareEpsilon) { + return false; + } + + if ((lhs.bitangent - rhs.bitangent).SquareLength() > squareEpsilon) { + return false; + } + + // Usually we won't have vertex colors or multiple UVs, so we can skip from here + // Actually this increases runtime performance slightly, at least if branch + // prediction is on our side. + if (complex) { + for (int i = 0; i < 8; i++) { + if (i > 0 && (lhs.texcoords[i] - rhs.texcoords[i]).SquareLength() > squareEpsilon) { + return false; + } + if (GetColorDifference(lhs.colors[i], rhs.colors[i]) > squareEpsilon) { + return false; + } + } + } + return true; +} + +template +void updateXMeshVertices(XMesh *pMesh, std::vector &uniqueVertices) { + // replace vertex data with the unique data sets + pMesh->mNumVertices = (unsigned int)uniqueVertices.size(); + + // ---------------------------------------------------------------------------- + // NOTE - we're *not* calling Vertex::SortBack() because it would check for + // presence of every single vertex component once PER VERTEX. And our CPU + // dislikes branches, even if they're easily predictable. + // ---------------------------------------------------------------------------- + + // Position, if present (check made for aiAnimMesh) + if (pMesh->mVertices) + { + delete [] pMesh->mVertices; + pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; + for (unsigned int a = 0; a < pMesh->mNumVertices; a++) { + pMesh->mVertices[a] = uniqueVertices[a].position; + } + } + + // Normals, if present + if (pMesh->mNormals) + { + delete [] pMesh->mNormals; + pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; + for( unsigned int a = 0; a < pMesh->mNumVertices; a++) { + pMesh->mNormals[a] = uniqueVertices[a].normal; + } + } + // Tangents, if present + if (pMesh->mTangents) + { + delete [] pMesh->mTangents; + pMesh->mTangents = new aiVector3D[pMesh->mNumVertices]; + for (unsigned int a = 0; a < pMesh->mNumVertices; a++) { + pMesh->mTangents[a] = uniqueVertices[a].tangent; + } + } + // Bitangents as well + if (pMesh->mBitangents) + { + delete [] pMesh->mBitangents; + pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices]; + for (unsigned int a = 0; a < pMesh->mNumVertices; a++) { + pMesh->mBitangents[a] = uniqueVertices[a].bitangent; + } + } + // Vertex colors + for (unsigned int a = 0; pMesh->HasVertexColors(a); a++) + { + delete [] pMesh->mColors[a]; + pMesh->mColors[a] = new aiColor4D[pMesh->mNumVertices]; + for( unsigned int b = 0; b < pMesh->mNumVertices; b++) { + pMesh->mColors[a][b] = uniqueVertices[b].colors[a]; + } + } + // Texture coords + for (unsigned int a = 0; pMesh->HasTextureCoords(a); a++) + { + delete [] pMesh->mTextureCoords[a]; + pMesh->mTextureCoords[a] = new aiVector3D[pMesh->mNumVertices]; + for (unsigned int b = 0; b < pMesh->mNumVertices; b++) { + pMesh->mTextureCoords[a][b] = uniqueVertices[b].texcoords[a]; + } + } +} +} // namespace + // ------------------------------------------------------------------------------------------------ // Unites identical vertices in the given mesh int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) @@ -138,9 +257,6 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) static_assert(AI_MAX_VERTICES == 0x7fffffff, "AI_MAX_VERTICES == 0x7fffffff"); std::vector replaceIndex( pMesh->mNumVertices, 0xffffffff); - // A little helper to find locally close vertices faster. - // Try to reuse the lookup table from the last step. - const static float epsilon = 1e-5f; // float posEpsilonSqr; SpatialSort* vertexFinder = NULL; SpatialSort _vertexFinder; @@ -162,9 +278,6 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) // posEpsilonSqr = ComputePositionEpsilon(pMesh); } - // Squared because we check against squared length of the vector difference - static const float squareEpsilon = epsilon * epsilon; - // Again, better waste some bytes than a realloc ... std::vector verticesFound; verticesFound.reserve(10); @@ -172,6 +285,16 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) // Run an optimized code path if we don't have multiple UVs or vertex colors. // This should yield false in more than 99% of all imports ... const bool complex = ( pMesh->GetNumColorChannels() > 0 || pMesh->GetNumUVChannels() > 1); + const bool hasAnimMeshes = pMesh->mNumAnimMeshes > 0; + + // We'll never have more vertices afterwards. + std::vector> uniqueAnimatedVertices; + if (hasAnimMeshes) { + uniqueAnimatedVertices.resize(pMesh->mNumAnimMeshes); + for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) { + uniqueAnimatedVertices[animMeshIndex].reserve(pMesh->mNumVertices); + } + } // Now check each vertex if it brings something new to the table for( unsigned int a = 0; a < pMesh->mNumVertices; a++) { @@ -184,74 +307,32 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) // check all unique vertices close to the position if this vertex is already present among them for( unsigned int b = 0; b < verticesFound.size(); b++) { - const unsigned int vidx = verticesFound[b]; const unsigned int uidx = replaceIndex[ vidx]; if( uidx & 0x80000000) continue; const Vertex& uv = uniqueVertices[ uidx]; - // Position mismatch is impossible - the vertex finder already discarded all non-matching positions - // We just test the other attributes even if they're not present in the mesh. - // In this case they're initialized to 0 so the comparison succeeds. - // By this method the non-present attributes are effectively ignored in the comparison. - if( (uv.normal - v.normal).SquareLength() > squareEpsilon) - continue; - if( (uv.texcoords[0] - v.texcoords[0]).SquareLength() > squareEpsilon) - continue; - if( (uv.tangent - v.tangent).SquareLength() > squareEpsilon) - continue; - if( (uv.bitangent - v.bitangent).SquareLength() > squareEpsilon) + if (!areVerticesEqual(v, uv, complex)) { continue; + } - // Usually we won't have vertex colors or multiple UVs, so we can skip from here - // Actually this increases runtime performance slightly, at least if branch - // prediction is on our side. - if (complex){ - // manually unrolled because continue wouldn't work as desired in an inner loop, - // also because some compilers seem to fail the task. Colors and UV coords - // are interleaved since the higher entries are most likely to be - // zero and thus useless. By interleaving the arrays, vertices are, - // on average, rejected earlier. - - if( (uv.texcoords[1] - v.texcoords[1]).SquareLength() > squareEpsilon) - continue; - if( GetColorDifference( uv.colors[0], v.colors[0]) > squareEpsilon) - continue; - - if( (uv.texcoords[2] - v.texcoords[2]).SquareLength() > squareEpsilon) - continue; - if( GetColorDifference( uv.colors[1], v.colors[1]) > squareEpsilon) - continue; - - if( (uv.texcoords[3] - v.texcoords[3]).SquareLength() > squareEpsilon) - continue; - if( GetColorDifference( uv.colors[2], v.colors[2]) > squareEpsilon) - continue; - - if( (uv.texcoords[4] - v.texcoords[4]).SquareLength() > squareEpsilon) - continue; - if( GetColorDifference( uv.colors[3], v.colors[3]) > squareEpsilon) - continue; - - if( (uv.texcoords[5] - v.texcoords[5]).SquareLength() > squareEpsilon) - continue; - if( GetColorDifference( uv.colors[4], v.colors[4]) > squareEpsilon) - continue; - - if( (uv.texcoords[6] - v.texcoords[6]).SquareLength() > squareEpsilon) - continue; - if( GetColorDifference( uv.colors[5], v.colors[5]) > squareEpsilon) - continue; - - if( (uv.texcoords[7] - v.texcoords[7]).SquareLength() > squareEpsilon) - continue; - if( GetColorDifference( uv.colors[6], v.colors[6]) > squareEpsilon) - continue; - - if( GetColorDifference( uv.colors[7], v.colors[7]) > squareEpsilon) + if (hasAnimMeshes) { + // If given vertex is animated, then it has to be preserver 1 to 1 (base mesh and animated mesh require same topology) + // NOTE: not doing this totaly breaks anim meshes as they don't have their own faces (they use pMesh->mFaces) + bool breaksAnimMesh = false; + for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) { + const Vertex& animatedUV = uniqueAnimatedVertices[animMeshIndex][ uidx]; + Vertex aniMeshVertex(pMesh->mAnimMeshes[animMeshIndex], a); + if (!areVerticesEqual(aniMeshVertex, animatedUV, complex)) { + breaksAnimMesh = true; + break; + } + } + if (breaksAnimMesh) { continue; + } } // we're still here -> this vertex perfectly matches our given vertex @@ -270,6 +351,12 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) // no unique vertex matches it up to now -> so add it replaceIndex[a] = (unsigned int)uniqueVertices.size(); uniqueVertices.push_back( v); + if (hasAnimMeshes) { + for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) { + Vertex aniMeshVertex(pMesh->mAnimMeshes[animMeshIndex], a); + uniqueAnimatedVertices[animMeshIndex].push_back(aniMeshVertex); + } + } } } @@ -287,64 +374,10 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) )); } - // replace vertex data with the unique data sets - pMesh->mNumVertices = (unsigned int)uniqueVertices.size(); - - // ---------------------------------------------------------------------------- - // NOTE - we're *not* calling Vertex::SortBack() because it would check for - // presence of every single vertex component once PER VERTEX. And our CPU - // dislikes branches, even if they're easily predictable. - // ---------------------------------------------------------------------------- - - // Position - delete [] pMesh->mVertices; - pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; - for( unsigned int a = 0; a < pMesh->mNumVertices; a++) - pMesh->mVertices[a] = uniqueVertices[a].position; - - // Normals, if present - if( pMesh->mNormals) - { - delete [] pMesh->mNormals; - pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; - for( unsigned int a = 0; a < pMesh->mNumVertices; a++) { - pMesh->mNormals[a] = uniqueVertices[a].normal; - } - } - // Tangents, if present - if( pMesh->mTangents) - { - delete [] pMesh->mTangents; - pMesh->mTangents = new aiVector3D[pMesh->mNumVertices]; - for( unsigned int a = 0; a < pMesh->mNumVertices; a++) { - pMesh->mTangents[a] = uniqueVertices[a].tangent; - } - } - // Bitangents as well - if( pMesh->mBitangents) - { - delete [] pMesh->mBitangents; - pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices]; - for( unsigned int a = 0; a < pMesh->mNumVertices; a++) { - pMesh->mBitangents[a] = uniqueVertices[a].bitangent; - } - } - // Vertex colors - for( unsigned int a = 0; pMesh->HasVertexColors(a); a++) - { - delete [] pMesh->mColors[a]; - pMesh->mColors[a] = new aiColor4D[pMesh->mNumVertices]; - for( unsigned int b = 0; b < pMesh->mNumVertices; b++) { - pMesh->mColors[a][b] = uniqueVertices[b].colors[a]; - } - } - // Texture coords - for( unsigned int a = 0; pMesh->HasTextureCoords(a); a++) - { - delete [] pMesh->mTextureCoords[a]; - pMesh->mTextureCoords[a] = new aiVector3D[pMesh->mNumVertices]; - for( unsigned int b = 0; b < pMesh->mNumVertices; b++) { - pMesh->mTextureCoords[a][b] = uniqueVertices[b].texcoords[a]; + updateXMeshVertices(pMesh, uniqueVertices); + if (hasAnimMeshes) { + for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) { + updateXMeshVertices(pMesh->mAnimMeshes[animMeshIndex], uniqueAnimatedVertices[animMeshIndex]); } } diff --git a/include/assimp/Vertex.h b/include/assimp/Vertex.h index 02ae3c0f4..f1c02ee07 100644 --- a/include/assimp/Vertex.h +++ b/include/assimp/Vertex.h @@ -134,6 +134,30 @@ public: } } + // ---------------------------------------------------------------------------- + /** Extract a particular vertex from a anim mesh and interleave all components */ + explicit Vertex(const aiAnimMesh* msh, unsigned int idx) { + ai_assert(idx < msh->mNumVertices); + position = msh->mVertices[idx]; + + if (msh->HasNormals()) { + normal = msh->mNormals[idx]; + } + + if (msh->HasTangentsAndBitangents()) { + tangent = msh->mTangents[idx]; + bitangent = msh->mBitangents[idx]; + } + + for (unsigned int i = 0; msh->HasTextureCoords(i); ++i) { + texcoords[i] = msh->mTextureCoords[i][idx]; + } + + for (unsigned int i = 0; msh->HasVertexColors(i); ++i) { + colors[i] = msh->mColors[i][idx]; + } + } + public: Vertex& operator += (const Vertex& v) { From 1533aec21c4d0aefba4810d2dc9fddf4990ab2a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Korbinian=20W=C3=BCrl?= Date: Fri, 27 Apr 2018 22:11:36 +0200 Subject: [PATCH 175/278] Fix ply exporter to be conformant to spec respecting vertex colors. Vertex colors should be defined as red, green, blue, alpha instead of r, g, b, a and should have the type 'uchar' instead of 'float' --- code/PlyExporter.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/code/PlyExporter.cpp b/code/PlyExporter.cpp index 2d528c96c..31c64a4d1 100644 --- a/code/PlyExporter.cpp +++ b/code/PlyExporter.cpp @@ -194,16 +194,16 @@ PlyExporter::PlyExporter(const char* _filename, const aiScene* pScene, bool bina for (unsigned int n = PLY_EXPORT_HAS_COLORS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_COLOR_SETS; n <<= 1, ++c) { if (!c) { - mOutput << "property " << typeName << " r" << endl; - mOutput << "property " << typeName << " g" << endl; - mOutput << "property " << typeName << " b" << endl; - mOutput << "property " << typeName << " a" << endl; + mOutput << "property " << "uchar" << " red" << endl; + mOutput << "property " << "uchar" << " green" << endl; + mOutput << "property " << "uchar" << " blue" << endl; + mOutput << "property " << "uchar" << " alpha" << endl; } else { - mOutput << "property " << typeName << " r" << c << endl; - mOutput << "property " << typeName << " g" << c << endl; - mOutput << "property " << typeName << " b" << c << endl; - mOutput << "property " << typeName << " a" << c << endl; + mOutput << "property " << "uchar" << " red" << c << endl; + mOutput << "property " << "uchar" << " green" << c << endl; + mOutput << "property " << "uchar" << " blue" << c << endl; + mOutput << "property " << "uchar" << " alpha" << c << endl; } } @@ -288,13 +288,13 @@ void PlyExporter::WriteMeshVerts(const aiMesh* m, unsigned int components) for (unsigned int n = PLY_EXPORT_HAS_COLORS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_COLOR_SETS; n <<= 1, ++c) { if (m->HasVertexColors(c)) { mOutput << - " " << m->mColors[c][i].r << - " " << m->mColors[c][i].g << - " " << m->mColors[c][i].b << - " " << m->mColors[c][i].a; + " " << (int)(m->mColors[c][i].r * 255) << + " " << (int)(m->mColors[c][i].g * 255) << + " " << (int)(m->mColors[c][i].b * 255) << + " " << (int)(m->mColors[c][i].a * 255); } else { - mOutput << " -1.0 -1.0 -1.0 -1.0"; + mOutput << " 0 0 0"; } } From 6fb9ebe3c891f05acccb08e7c89d70077409b2bd Mon Sep 17 00:00:00 2001 From: Trylz Date: Sat, 28 Apr 2018 23:34:07 -0400 Subject: [PATCH 176/278] Apply fix --- code/FBXConverter.cpp | 27 ++++++++++++++++----------- code/FBXConverter.h | 10 +++++----- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 2c9818a16..d6529d119 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -874,7 +874,7 @@ void Converter::ConvertModel( const Model& model, aiNode& nd, const aiMatrix4x4& const MeshGeometry* const mesh = dynamic_cast< const MeshGeometry* >( geo ); if ( mesh ) { - const std::vector& indices = ConvertMesh( *mesh, model, node_global_transform ); + const std::vector& indices = ConvertMesh( *mesh, model, node_global_transform, nd); std::copy( indices.begin(), indices.end(), std::back_inserter( meshes ) ); } else { @@ -891,7 +891,7 @@ void Converter::ConvertModel( const Model& model, aiNode& nd, const aiMatrix4x4& } std::vector Converter::ConvertMesh( const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform ) + const aiMatrix4x4& node_global_transform, aiNode& nd) { std::vector temp; @@ -915,17 +915,17 @@ std::vector Converter::ConvertMesh( const MeshGeometry& mesh, cons const MatIndexArray::value_type base = mindices[ 0 ]; for( MatIndexArray::value_type index : mindices ) { if ( index != base ) { - return ConvertMeshMultiMaterial( mesh, model, node_global_transform ); + return ConvertMeshMultiMaterial( mesh, model, node_global_transform, nd); } } } // faster code-path, just copy the data - temp.push_back( ConvertMeshSingleMaterial( mesh, model, node_global_transform ) ); + temp.push_back( ConvertMeshSingleMaterial( mesh, model, node_global_transform, nd) ); return temp; } -aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh ) +aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh, aiNode& nd) { aiMesh* const out_mesh = new aiMesh(); meshes.push_back( out_mesh ); @@ -940,15 +940,19 @@ aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh ) if ( name.length() ) { out_mesh->mName.Set( name ); } + else + { + out_mesh->mName = nd.mName; + } return out_mesh; } unsigned int Converter::ConvertMeshSingleMaterial( const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform ) + const aiMatrix4x4& node_global_transform, aiNode& nd) { const MatIndexArray& mindices = mesh.GetMaterialIndices(); - aiMesh* const out_mesh = SetupEmptyMesh( mesh ); + aiMesh* const out_mesh = SetupEmptyMesh(mesh, nd); const std::vector& vertices = mesh.GetVertices(); const std::vector& faces = mesh.GetFaceIndexCounts(); @@ -1072,7 +1076,7 @@ unsigned int Converter::ConvertMeshSingleMaterial( const MeshGeometry& mesh, con } std::vector Converter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform ) + const aiMatrix4x4& node_global_transform, aiNode& nd) { const MatIndexArray& mindices = mesh.GetMaterialIndices(); ai_assert( mindices.size() ); @@ -1083,7 +1087,7 @@ std::vector Converter::ConvertMeshMultiMaterial( const MeshGeometr for( MatIndexArray::value_type index : mindices ) { if ( had.find( index ) == had.end() ) { - indices.push_back( ConvertMeshMultiMaterial( mesh, model, index, node_global_transform ) ); + indices.push_back( ConvertMeshMultiMaterial( mesh, model, index, node_global_transform, nd) ); had.insert( index ); } } @@ -1093,9 +1097,10 @@ std::vector Converter::ConvertMeshMultiMaterial( const MeshGeometr unsigned int Converter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model, MatIndexArray::value_type index, - const aiMatrix4x4& node_global_transform ) + const aiMatrix4x4& node_global_transform, + aiNode& nd) { - aiMesh* const out_mesh = SetupEmptyMesh( mesh ); + aiMesh* const out_mesh = SetupEmptyMesh(mesh, nd); const MatIndexArray& mindices = mesh.GetMaterialIndices(); const std::vector& vertices = mesh.GetVertices(); diff --git a/code/FBXConverter.h b/code/FBXConverter.h index 60fd04e2c..71d93d339 100644 --- a/code/FBXConverter.h +++ b/code/FBXConverter.h @@ -172,23 +172,23 @@ private: // ------------------------------------------------------------------------------------------------ // MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed std::vector ConvertMesh(const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform); + const aiMatrix4x4& node_global_transform, aiNode& nd); // ------------------------------------------------------------------------------------------------ - aiMesh* SetupEmptyMesh(const MeshGeometry& mesh); + aiMesh* SetupEmptyMesh(const MeshGeometry& mesh, aiNode& nd); // ------------------------------------------------------------------------------------------------ unsigned int ConvertMeshSingleMaterial(const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform); + const aiMatrix4x4& node_global_transform, aiNode& nd); // ------------------------------------------------------------------------------------------------ std::vector ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform); + const aiMatrix4x4& node_global_transform, aiNode& nd); // ------------------------------------------------------------------------------------------------ unsigned int ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model, MatIndexArray::value_type index, - const aiMatrix4x4& node_global_transform); + const aiMatrix4x4& node_global_transform, aiNode& nd); // ------------------------------------------------------------------------------------------------ static const unsigned int NO_MATERIAL_SEPARATION = /* std::numeric_limits::max() */ From 9e484daa65dc7993d39e89fa612f91b59f43bc2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Korbinian=20W=C3=BCrl?= Date: Mon, 30 Apr 2018 15:51:48 +0200 Subject: [PATCH 177/278] Unit test for Issue #1923: OBJ Exporter can't correctly export vertex colors --- .../models/OBJ/cube_with_vertexcolors_uni.obj | 30 +++++++++++++++++++ test/unit/utObjImportExport.cpp | 18 +++++++++++ 2 files changed, 48 insertions(+) create mode 100644 test/models/OBJ/cube_with_vertexcolors_uni.obj diff --git a/test/models/OBJ/cube_with_vertexcolors_uni.obj b/test/models/OBJ/cube_with_vertexcolors_uni.obj new file mode 100644 index 000000000..c698b9489 --- /dev/null +++ b/test/models/OBJ/cube_with_vertexcolors_uni.obj @@ -0,0 +1,30 @@ +g cube + +v 0.0 0.0 0.0 0.0 0.0 0.0 +v 0.0 0.0 1.0 1.0 0.6 0.3 +v 0.0 1.0 0.0 0.0 0.0 0.0 +v 0.0 1.0 1.0 0.3 0.6 1.0 +v 1.0 0.0 0.0 0.0 0.0 0.0 +v 1.0 0.0 1.0 1.0 0.6 0.3 +v 1.0 1.0 0.0 0.0 0.0 0.0 +v 1.0 1.0 1.0 0.3 0.6 1.0 + +vn 0.0 0.0 1.0 +vn 0.0 0.0 -1.0 +vn 0.0 1.0 0.0 +vn 0.0 -1.0 0.0 +vn 1.0 0.0 0.0 +vn -1.0 0.0 0.0 + +f 1//2 7//2 5//2 +f 1//2 3//2 7//2 +f 1//6 4//6 3//6 +f 1//6 2//6 4//6 +f 3//3 8//3 7//3 +f 3//3 4//3 8//3 +f 5//5 7//5 8//5 +f 5//5 8//5 6//5 +f 1//4 5//4 6//4 +f 1//4 6//4 2//4 +f 2//1 6//1 8//1 +f 2//1 8//1 4//1 \ No newline at end of file diff --git a/test/unit/utObjImportExport.cpp b/test/unit/utObjImportExport.cpp index 8aec9c443..e879c350e 100644 --- a/test/unit/utObjImportExport.cpp +++ b/test/unit/utObjImportExport.cpp @@ -267,6 +267,24 @@ TEST_F( utObjImportExport, issue809_vertex_color_Test ) { #endif // ASSIMP_BUILD_NO_EXPORT } +TEST_F( utObjImportExport, issue1923_vertex_color_Test ) { + ::Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/cube_with_vertexcolors_uni.obj", aiProcess_ValidateDataStructure ); + EXPECT_NE( nullptr, scene ); + +#ifndef ASSIMP_BUILD_NO_EXPORT + ::Assimp::Exporter exporter; + const aiExportDataBlob* blob = exporter.ExportToBlob( scene, "obj"); + EXPECT_NE( nullptr, blob ); + + const aiScene *sceneReImport = importer.ReadFileFromMemory( blob->data, blob->size, aiProcess_ValidateDataStructure ); + EXPECT_NE( nullptr, scene ); + + SceneDiffer differ; + EXPECT_TRUE( differ.isEqual( scene, sceneReImport ) ); +#endif // ASSIMP_BUILD_NO_EXPORT +} + TEST_F( utObjImportExport, issue1453_segfault ) { static const std::string ObjModel = "v 0.0 0.0 0.0\n" From 9cfdb8d3658f306163d2eb33eaaeb16c5a2eb429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Korbinian=20W=C3=BCrl?= Date: Mon, 30 Apr 2018 16:23:29 +0200 Subject: [PATCH 178/278] Fixed test .obj file: OBJ Vertex Colors are expected to be floats 0-1 See https://github.com/cnr-isti-vclab/vcglib/blob/master/wrap/io_trimesh/import_obj.h#L326 --- test/models/OBJ/cube_with_vertexcolors.obj | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/models/OBJ/cube_with_vertexcolors.obj b/test/models/OBJ/cube_with_vertexcolors.obj index d78d3a555..1541e0823 100644 --- a/test/models/OBJ/cube_with_vertexcolors.obj +++ b/test/models/OBJ/cube_with_vertexcolors.obj @@ -1,13 +1,13 @@ g cube -v 0.0 0.0 0.0 124 110 120 -v 0.0 0.0 1.0 24 0 121 -v 0.0 1.0 0.0 4 0 44 -v 0.0 1.0 1.0 224 0 10 -v 1.0 0.0 0.0 24 200 25 -v 1.0 0.0 1.0 124 10 56 -v 1.0 1.0 0.0 78 10 50 -v 1.0 1.0 1.0 23 0 200 +v 0.0 0.0 0.0 0.48627 0.43137 0.47059 +v 0.0 0.0 1.0 0.09412 0.00000 0.47451 +v 0.0 1.0 0.0 0.01569 0.00000 0.17255 +v 0.0 1.0 1.0 0.87843 0.00000 0.03922 +v 1.0 0.0 0.0 0.09412 0.78431 0.09804 +v 1.0 0.0 1.0 0.48627 0.03922 0.21961 +v 1.0 1.0 0.0 0.30588 0.03922 0.19608 +v 1.0 1.0 1.0 0.09020 0.00000 0.78431 vn 0.0 0.0 1.0 vn 0.0 0.0 -1.0 From 4b7b692e5e72f70ae001a274ccd78a4ffde35d9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Korbinian=20W=C3=BCrl?= Date: Mon, 30 Apr 2018 16:27:34 +0200 Subject: [PATCH 179/278] Fix Issue #1923: OBJ Exporter can't correctly export vertex colors The indexMap for vertices now uses a combined vp + vc index --- code/ObjExporter.cpp | 90 ++++++++++------------------------------ code/ObjExporter.h | 99 +++++++++++++++++++++++++------------------- 2 files changed, 78 insertions(+), 111 deletions(-) diff --git a/code/ObjExporter.cpp b/code/ObjExporter.cpp index 6cd69f402..1542efebf 100644 --- a/code/ObjExporter.cpp +++ b/code/ObjExporter.cpp @@ -114,14 +114,13 @@ static const std::string MaterialExt = ".mtl"; ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMtl) : filename(_filename) , pScene(pScene) -, vp() , vn() , vt() -, vc() -, mVpMap() +, vp() +, useVc(false) , mVnMap() , mVtMap() -, mVcMap() +, mVpMap() , mMeshes() , endl("\n") { // make sure that all formatting happens using the standard, C locale and not the user's current locale @@ -268,27 +267,22 @@ void ObjExporter::WriteGeometryFile(bool noMtl) { AddNode(pScene->mRootNode, mBase); // write vertex positions with colors, if any - mVpMap.getVectors( vp ); - mVcMap.getColors( vc ); - if ( vc.empty() ) { + mVpMap.getKeys( vp ); + if ( !useVc ) { mOutput << "# " << vp.size() << " vertex positions" << endl; - for ( const aiVector3D& v : vp ) { - mOutput << "v " << v.x << " " << v.y << " " << v.z << endl; + for ( const vertexData& v : vp ) { + mOutput << "v " << v.vp.x << " " << v.vp.y << " " << v.vp.z << endl; } } else { mOutput << "# " << vp.size() << " vertex positions and colors" << endl; - size_t colIdx = 0; - for ( const aiVector3D& v : vp ) { - if ( colIdx < vc.size() ) { - mOutput << "v " << v.x << " " << v.y << " " << v.z << " " << vc[ colIdx ].r << " " << vc[ colIdx ].g << " " << vc[ colIdx ].b << endl; - } - ++colIdx; + for ( const vertexData& v : vp ) { + mOutput << "v " << v.vp.x << " " << v.vp.y << " " << v.vp.z << " " << v.vc.r << " " << v.vc.g << " " << v.vc.b << endl; } } mOutput << endl; // write uv coordinates - mVtMap.getVectors(vt); + mVtMap.getKeys(vt); mOutput << "# " << vt.size() << " UV coordinates" << endl; for(const aiVector3D& v : vt) { mOutput << "vt " << v.x << " " << v.y << " " << v.z << endl; @@ -296,7 +290,7 @@ void ObjExporter::WriteGeometryFile(bool noMtl) { mOutput << endl; // write vertex normals - mVnMap.getVectors(vn); + mVnMap.getKeys(vn); mOutput << "# " << vn.size() << " vertex normals" << endl; for(const aiVector3D& v : vn) { mOutput << "vn " << v.x << " " << v.y << " " << v.z << endl; @@ -337,54 +331,15 @@ void ObjExporter::WriteGeometryFile(bool noMtl) { } } -// ------------------------------------------------------------------------------------------------ -int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec) { - vecIndexMap::dataType::iterator vertIt = vecMap.find(vec); - // vertex already exists, so reference it - if(vertIt != vecMap.end()){ - return vertIt->second; - } - vecMap[vec] = mNextIndex; - int ret = mNextIndex; - mNextIndex++; - return ret; -} - -// ------------------------------------------------------------------------------------------------ -void ObjExporter::vecIndexMap::getVectors( std::vector& vecs ) { - vecs.resize(vecMap.size()); - for(vecIndexMap::dataType::iterator it = vecMap.begin(); it != vecMap.end(); ++it){ - vecs[it->second-1] = it->first; - } -} - -// ------------------------------------------------------------------------------------------------ -int ObjExporter::colIndexMap::getIndex( const aiColor4D& col ) { - colIndexMap::dataType::iterator vertIt = colMap.find( col ); - // vertex already exists, so reference it - if ( vertIt != colMap.end() ) { - return vertIt->second; - } - colMap[ col ] = mNextIndex; - int ret = mNextIndex; - mNextIndex++; - - return ret; -} - -// ------------------------------------------------------------------------------------------------ -void ObjExporter::colIndexMap::getColors( std::vector &colors ) { - colors.resize( colMap.size() ); - for ( colIndexMap::dataType::iterator it = colMap.begin(); it != colMap.end(); ++it ) { - colors[ it->second - 1 ] = it->first; - } -} - // ------------------------------------------------------------------------------------------------ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) { mMeshes.push_back(MeshInstance() ); MeshInstance& mesh = mMeshes.back(); + if ( nullptr != m->mColors[ 0 ] ) { + useVc = true; + } + mesh.name = std::string( name.data, name.length ); mesh.matname = GetMaterialName(m->mMaterialIndex); @@ -410,7 +365,13 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4 const unsigned int idx = f.mIndices[a]; aiVector3D vert = mat * m->mVertices[idx]; - face.indices[a].vp = mVpMap.getIndex(vert); + + if ( nullptr != m->mColors[ 0 ] ) { + aiColor4D col4 = m->mColors[ 0 ][ idx ]; + face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(col4.r, col4.g, col4.b)}); + } else { + face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(0,0,0)}); + } if (m->mNormals) { aiVector3D norm = aiMatrix3x3(mat) * m->mNormals[idx]; @@ -419,13 +380,6 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4 face.indices[a].vn = 0; } - if ( nullptr != m->mColors[ 0 ] ) { - aiColor4D col4 = m->mColors[ 0 ][ idx ]; - face.indices[ a ].vc = mVcMap.getIndex( col4 ); - } else { - face.indices[ a ].vc = 0; - } - if ( m->mTextureCoords[ 0 ] ) { face.indices[a].vt = mVtMap.getIndex(m->mTextureCoords[0][idx]); } else { diff --git a/code/ObjExporter.h b/code/ObjExporter.h index 7920598d0..bd745b593 100644 --- a/code/ObjExporter.h +++ b/code/ObjExporter.h @@ -77,13 +77,12 @@ private: FaceVertex() : vp() , vn() - , vt() - , vc() { + , vt() { // empty } // one-based, 0 means: 'does not exist' - unsigned int vp, vn, vt, vc; + unsigned int vp, vn, vt; }; struct Face { @@ -106,66 +105,80 @@ private: private: std::string filename; const aiScene* const pScene; - std::vector vp, vn, vt; + + struct vertexData { + aiVector3D vp; + aiColor3D vc; // OBJ does not support 4D color + }; + + std::vector vn, vt; std::vector vc; + std::vector vp; + bool useVc; - struct aiVectorCompare { - bool operator() (const aiVector3D& a, const aiVector3D& b) const { - if(a.x < b.x) return true; - if(a.x > b.x) return false; - if(a.y < b.y) return true; - if(a.y > b.y) return false; - if(a.z < b.z) return true; + struct vertexDataCompare { + bool operator() ( const vertexData& a, const vertexData& b ) const { + // position + if (a.vp.x < b.vp.x) return true; + if (a.vp.x > b.vp.x) return false; + if (a.vp.y < b.vp.y) return true; + if (a.vp.y > b.vp.y) return false; + if (a.vp.z < b.vp.z) return true; + if (a.vp.z > b.vp.z) return false; + + // color + if (a.vc.r < b.vc.r) return true; + if (a.vc.r > b.vc.r) return false; + if (a.vc.g < b.vc.g) return true; + if (a.vc.g > b.vc.g) return false; + if (a.vc.b < b.vc.b) return true; + if (a.vc.b > b.vc.b) return false; return false; } }; - struct aiColor4Compare { - bool operator() ( const aiColor4D& a, const aiColor4D& b ) const { - if ( a.r < b.r ) return true; - if ( a.r > b.r ) return false; - if ( a.g < b.g ) return true; - if ( a.g > b.g ) return false; - if ( a.b < b.b ) return true; - if ( a.b > b.b ) return false; - if ( a.a < b.a ) return true; - if ( a.a > b.a ) return false; + struct aiVectorCompare { + bool operator() (const aiVector3D& a, const aiVector3D& b) const { + if(a.x < b.x) return true; + if(a.x > b.x) return false; + if(a.y < b.y) return true; + if(a.y > b.y) return false; + if(a.z < b.z) return true; return false; } }; - class vecIndexMap { + template > + class indexMap { int mNextIndex; - typedef std::map dataType; + typedef std::map dataType; dataType vecMap; public: - vecIndexMap() + indexMap() : mNextIndex(1) { // empty } - int getIndex(const aiVector3D& vec); - void getVectors( std::vector& vecs ); + int getIndex(const T& key) { + typename dataType::iterator vertIt = vecMap.find(key); + // vertex already exists, so reference it + if(vertIt != vecMap.end()){ + return vertIt->second; + } + return vecMap[key] = mNextIndex++; + }; + + void getKeys( std::vector& keys ) { + keys.resize(vecMap.size()); + for(typename dataType::iterator it = vecMap.begin(); it != vecMap.end(); ++it){ + keys[it->second-1] = it->first; + } + }; }; - class colIndexMap { - int mNextIndex; - typedef std::map dataType; - dataType colMap; - - public: - colIndexMap() - : mNextIndex( 1 ) { - // empty - } - - int getIndex( const aiColor4D& col ); - void getColors( std::vector &colors ); - }; - - vecIndexMap mVpMap, mVnMap, mVtMap; - colIndexMap mVcMap; + indexMap mVnMap, mVtMap; + indexMap mVpMap; std::vector mMeshes; // this endl() doesn't flush() the stream From 9f835ea8435ddb7999a4d57eb388ada230db1ef3 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 1 May 2018 09:06:22 +0200 Subject: [PATCH 180/278] closes https://github.com/assimp/assimp/issues/842: experimental suppor for ascii stl pointcloud export. --- code/STLExporter.cpp | 40 ++++++++++++++++++++++++++++++++----- code/STLExporter.h | 4 +--- code/simd.cpp | 1 + include/assimp/Exporter.hpp | 14 +++++++------ include/assimp/cexport.h | 6 ++---- include/assimp/config.h.in | 5 +++++ 6 files changed, 52 insertions(+), 18 deletions(-) diff --git a/code/STLExporter.cpp b/code/STLExporter.cpp index 3d681f8c7..5f9bfbde2 100644 --- a/code/STLExporter.cpp +++ b/code/STLExporter.cpp @@ -54,14 +54,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include using namespace Assimp; + namespace Assimp { // ------------------------------------------------------------------------------------------------ // Worker function for exporting a scene to Stereolithograpy. Prototyped and registered in Exporter.cpp -void ExportSceneSTL(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) +void ExportSceneSTL(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties ) { + bool exportPointClouds = pProperties->GetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS); + // invoke the exporter - STLExporter exporter(pFile, pScene); + STLExporter exporter(pFile, pScene, exportPointClouds ); if (exporter.mOutput.fail()) { throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile)); @@ -75,10 +78,12 @@ void ExportSceneSTL(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene outfile->Write( exporter.mOutput.str().c_str(), static_cast(exporter.mOutput.tellp()),1); } -void ExportSceneSTLBinary(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) +void ExportSceneSTLBinary(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties ) { + bool exportPointClouds = pProperties->GetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS); + // invoke the exporter - STLExporter exporter(pFile, pScene, true); + STLExporter exporter(pFile, pScene, exportPointClouds, true); if (exporter.mOutput.fail()) { throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile)); @@ -97,7 +102,7 @@ void ExportSceneSTLBinary(const char* pFile,IOSystem* pIOSystem, const aiScene* // ------------------------------------------------------------------------------------------------ -STLExporter :: STLExporter(const char* _filename, const aiScene* pScene, bool binary) +STLExporter::STLExporter(const char* _filename, const aiScene* pScene, bool exportPointClouds, bool binary) : filename(_filename) , endl("\n") { @@ -118,12 +123,37 @@ STLExporter :: STLExporter(const char* _filename, const aiScene* pScene, bool bi } AI_SWAP4(meshnum); mOutput.write((char *)&meshnum, 4); + + if (exportPointClouds) { + + } + for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) { WriteMeshBinary(pScene->mMeshes[i]); } } else { const std::string& name = "AssimpScene"; + // Exporting only point clouds + if (exportPointClouds) { + mOutput << "solid " << name << endl; + aiVector3D nor; + mOutput << " facet normal " << nor.x << " " << nor.y << " " << nor.z << endl; + for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { + aiMesh *mesh = pScene->mMeshes[i]; + if (mesh->mNormals) { + for (unsigned int a = 0; a < mesh->mNumVertices; ++a) { + const aiVector3D& v = mesh->mVertices[a]; + mOutput << " vertex " << v.x << " " << v.y << " " << v.z << endl; + mOutput << " vertex " << v.x << " " << v.y << " " << v.z << endl; + mOutput << " vertex " << v.x << " " << v.y << " " << v.z << endl; + } + } + } + mOutput << "endsolid " << name << endl; + return; + } + mOutput << "solid " << name << endl; for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) { WriteMesh(pScene->mMeshes[i]); diff --git a/code/STLExporter.h b/code/STLExporter.h index 1bd589627..a1d306944 100644 --- a/code/STLExporter.h +++ b/code/STLExporter.h @@ -62,9 +62,7 @@ class STLExporter { public: /// Constructor for a specific scene to export - STLExporter(const char* filename, const aiScene* pScene, bool binary = false); - -public: + STLExporter(const char* filename, const aiScene* pScene, bool exportPOintClouds, bool binary = false); /// public stringstreams to write all output into std::ostringstream mOutput; diff --git a/code/simd.cpp b/code/simd.cpp index bd951bffa..9e2a83a60 100644 --- a/code/simd.cpp +++ b/code/simd.cpp @@ -75,4 +75,5 @@ bool CPUSupportsSSE2() { #endif } + } // Namespace Assimp diff --git a/include/assimp/Exporter.hpp b/include/assimp/Exporter.hpp index e7e43d8b7..dfbac9371 100644 --- a/include/assimp/Exporter.hpp +++ b/include/assimp/Exporter.hpp @@ -115,12 +115,10 @@ public: } }; - public: Exporter(); ~Exporter(); -public: // ------------------------------------------------------------------- /** Supplies a custom IO handler to the exporter to use to open and * access files. @@ -172,8 +170,10 @@ public: * Any IO handlers set via #SetIOHandler are ignored here. * @note Use aiCopyScene() to get a modifiable copy of a previously * imported scene. */ - const aiExportDataBlob* ExportToBlob(const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing = 0u, const ExportProperties* = NULL); - const aiExportDataBlob* ExportToBlob( const aiScene* pScene, const std::string& pFormatId, unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = NULL); + const aiExportDataBlob* ExportToBlob(const aiScene* pScene, const char* pFormatId, + unsigned int pPreprocessing = 0u, const ExportProperties* = nullptr); + const aiExportDataBlob* ExportToBlob( const aiScene* pScene, const std::string& pFormatId, + unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = nullptr); // ------------------------------------------------------------------- /** Convenience function to export directly to a file. Use @@ -208,8 +208,10 @@ public: * @return AI_SUCCESS if everything was fine. * @note Use aiCopyScene() to get a modifiable copy of a previously * imported scene.*/ - aiReturn Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = NULL); - aiReturn Export( const aiScene* pScene, const std::string& pFormatId, const std::string& pPath, unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = NULL); + aiReturn Export( const aiScene* pScene, const char* pFormatId, const char* pPath, + unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = nullptr); + aiReturn Export( const aiScene* pScene, const std::string& pFormatId, const std::string& pPath, + unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = nullptr); // ------------------------------------------------------------------- /** Returns an error description of an error that occurred in #Export diff --git a/include/assimp/cexport.h b/include/assimp/cexport.h index 44b06fb3c..1d62dc26b 100644 --- a/include/assimp/cexport.h +++ b/include/assimp/cexport.h @@ -85,7 +85,6 @@ struct aiExportFormatDesc */ ASSIMP_API size_t aiGetExportFormatCount(void); - // -------------------------------------------------------------------------------- /** Returns a description of the nth export file format. Use #aiGetExportFormatCount() * to learn how many export formats are supported. The description must be released by @@ -186,7 +185,6 @@ ASSIMP_API aiReturn aiExportSceneEx( const C_STRUCT aiScene* pScene, C_STRUCT aiFileIO* pIO, unsigned int pPreprocessing ); - // -------------------------------------------------------------------------------- /** Describes a blob of exported scene data. Use #aiExportSceneToBlob() to create a blob containing an * exported scene. The memory referred by this structure is owned by Assimp. @@ -245,8 +243,8 @@ private: * @param pPreprocessing Please see the documentation for #aiExportScene * @return the exported data or NULL in case of error */ -ASSIMP_API const C_STRUCT aiExportDataBlob* aiExportSceneToBlob( const C_STRUCT aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing ); - +ASSIMP_API const C_STRUCT aiExportDataBlob* aiExportSceneToBlob( const C_STRUCT aiScene* pScene, const char* pFormatId, + unsigned int pPreprocessing ); // -------------------------------------------------------------------------------- /** Releases the memory associated with the given exported data. Use this function to free a data blob diff --git a/include/assimp/config.h.in b/include/assimp/config.h.in index c9555fb38..8de2ea43e 100644 --- a/include/assimp/config.h.in +++ b/include/assimp/config.h.in @@ -953,6 +953,11 @@ enum aiComponent #define AI_CONFIG_EXPORT_XFILE_64BIT "EXPORT_XFILE_64BIT" +/** + * + */ +#define AI_CONFIG_EXPORT_POINT_CLOUDS "EXPORT_POINT_CLOUDS" + /** * @brief Specifies a gobal key factor for scale, float value */ From 22475130649c3d356c507a7a420ce176d0b45d38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Korbinian=20W=C3=BCrl?= Date: Tue, 1 May 2018 11:23:38 +0200 Subject: [PATCH 181/278] Fix for TravisCI --- test/unit/utObjImportExport.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/unit/utObjImportExport.cpp b/test/unit/utObjImportExport.cpp index e879c350e..5a10ae17b 100644 --- a/test/unit/utObjImportExport.cpp +++ b/test/unit/utObjImportExport.cpp @@ -272,6 +272,8 @@ TEST_F( utObjImportExport, issue1923_vertex_color_Test ) { const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/cube_with_vertexcolors_uni.obj", aiProcess_ValidateDataStructure ); EXPECT_NE( nullptr, scene ); + scene = importer.GetOrphanedScene(); + #ifndef ASSIMP_BUILD_NO_EXPORT ::Assimp::Exporter exporter; const aiExportDataBlob* blob = exporter.ExportToBlob( scene, "obj"); @@ -283,6 +285,8 @@ TEST_F( utObjImportExport, issue1923_vertex_color_Test ) { SceneDiffer differ; EXPECT_TRUE( differ.isEqual( scene, sceneReImport ) ); #endif // ASSIMP_BUILD_NO_EXPORT + + delete scene; } TEST_F( utObjImportExport, issue1453_segfault ) { From 2c47717ca6cb54c9da9623edaf2da44da430bc63 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 1 May 2018 13:28:53 +0200 Subject: [PATCH 182/278] Introduce export with test for point clouds. --- code/Exporter.cpp | 14 ++++++-- code/PretransformVertices.cpp | 20 ++++++----- code/PretransformVertices.h | 9 ++--- code/RemoveRedundantMaterials.h | 1 + code/STLExporter.cpp | 18 +++++----- code/STLExporter.h | 3 +- test/unit/utPLYImportExport.cpp | 21 ++++++------ test/unit/utSTLImportExport.cpp | 61 +++++++++++++++++++++++++++++++++ 8 files changed, 109 insertions(+), 38 deletions(-) diff --git a/code/Exporter.cpp b/code/Exporter.cpp index 0a8f054b7..53a623ecd 100644 --- a/code/Exporter.cpp +++ b/code/Exporter.cpp @@ -62,6 +62,7 @@ Here we implement only the C++ interface (Assimp::Exporter). #include "JoinVerticesProcess.h" #include "MakeVerboseFormat.h" #include "ConvertToLHProcess.h" +#include "PretransformVertices.h" #include #include "ScenePrivate.h" #include @@ -397,6 +398,11 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c } } + bool exportPointCloud(false); + if (nullptr != pProperties) { + exportPointCloud = pProperties->GetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS); + } + // dispatch other processes for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) { BaseProcess* const p = pimpl->mPostProcessingSteps[a]; @@ -405,7 +411,9 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c && !dynamic_cast(p) && !dynamic_cast(p) && !dynamic_cast(p)) { - + if (dynamic_cast(p) && exportPointCloud) { + continue; + } p->Execute(scenecopy.get()); } } @@ -441,7 +449,6 @@ const char* Exporter::GetErrorString() const { return pimpl->mError.c_str(); } - // ------------------------------------------------------------------------------------------------ void Exporter::FreeBlob() { delete pimpl->blob; @@ -495,7 +502,8 @@ aiReturn Exporter::RegisterExporter(const ExportFormatEntry& desc) { // ------------------------------------------------------------------------------------------------ void Exporter::UnregisterExporter(const char* id) { - for(std::vector::iterator it = pimpl->mExporters.begin(); it != pimpl->mExporters.end(); ++it) { + for(std::vector::iterator it = pimpl->mExporters.begin(); + it != pimpl->mExporters.end(); ++it) { if (!strcmp((*it).mDescription.id,id)) { pimpl->mExporters.erase(it); break; diff --git a/code/PretransformVertices.cpp b/code/PretransformVertices.cpp index 0623f00ef..9745abd60 100644 --- a/code/PretransformVertices.cpp +++ b/code/PretransformVertices.cpp @@ -60,14 +60,17 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer PretransformVertices::PretransformVertices() -: configKeepHierarchy (false), configNormalize(false), configTransform(false), configTransformation() -{ +: configKeepHierarchy (false) +, configNormalize(false) +, configTransform(false) +, configTransformation() +, mConfigPointCloud( false ) { + // empty } // ------------------------------------------------------------------------------------------------ // Destructor, private as well -PretransformVertices::~PretransformVertices() -{ +PretransformVertices::~PretransformVertices() { // nothing to do here } @@ -89,6 +92,8 @@ void PretransformVertices::SetupProperties(const Importer* pImp) configTransform = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION,0)); configTransformation = pImp->GetPropertyMatrix(AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION, aiMatrix4x4()); + + mConfigPointCloud = pImp->GetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS); } // ------------------------------------------------------------------------------------------------ @@ -502,9 +507,7 @@ void PretransformVertices::Execute( aiScene* pScene) pScene->mMeshes[i]->mBones = NULL; pScene->mMeshes[i]->mNumBones = 0; } - } - else { - + } else { apcOutMeshes.reserve(pScene->mNumMaterials<<1u); std::list aiVFormats; @@ -556,7 +559,8 @@ void PretransformVertices::Execute( aiScene* pScene) } // If no meshes are referenced in the node graph it is possible that we get no output meshes. - if (apcOutMeshes.empty()) { + if (apcOutMeshes.empty()) { + throw DeadlyImportError("No output meshes: all meshes are orphaned and are not referenced by any nodes"); } else diff --git a/code/PretransformVertices.h b/code/PretransformVertices.h index 8b400dc0c..a8196289d 100644 --- a/code/PretransformVertices.h +++ b/code/PretransformVertices.h @@ -61,15 +61,11 @@ namespace Assimp { * and removes the whole graph. The output is a list of meshes, one for * each material. */ -class ASSIMP_API PretransformVertices : public BaseProcess -{ +class ASSIMP_API PretransformVertices : public BaseProcess { public: - PretransformVertices (); ~PretransformVertices (); -public: - // ------------------------------------------------------------------- // Check whether step is active bool IsActive( unsigned int pFlags) const; @@ -82,7 +78,6 @@ public: // Setup import settings void SetupProperties(const Importer* pImp); - // ------------------------------------------------------------------- /** @brief Toggle the 'keep hierarchy' option * @param d hm ... difficult to guess what this means, hu!? @@ -100,7 +95,6 @@ public: } private: - // ------------------------------------------------------------------- // Count the number of nodes unsigned int CountNodes( aiNode* pcNode ); @@ -161,6 +155,7 @@ private: bool configNormalize; bool configTransform; aiMatrix4x4 configTransformation; + bool mConfigPointCloud; }; } // end of namespace Assimp diff --git a/code/RemoveRedundantMaterials.h b/code/RemoveRedundantMaterials.h index 37b69ffbe..314bbf345 100644 --- a/code/RemoveRedundantMaterials.h +++ b/code/RemoveRedundantMaterials.h @@ -50,6 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include class RemoveRedundantMatsTest; + namespace Assimp { // --------------------------------------------------------------------------- diff --git a/code/STLExporter.cpp b/code/STLExporter.cpp index 5f9bfbde2..dd4df9212 100644 --- a/code/STLExporter.cpp +++ b/code/STLExporter.cpp @@ -141,13 +141,15 @@ STLExporter::STLExporter(const char* _filename, const aiScene* pScene, bool expo mOutput << " facet normal " << nor.x << " " << nor.y << " " << nor.z << endl; for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { aiMesh *mesh = pScene->mMeshes[i]; - if (mesh->mNormals) { - for (unsigned int a = 0; a < mesh->mNumVertices; ++a) { - const aiVector3D& v = mesh->mVertices[a]; - mOutput << " vertex " << v.x << " " << v.y << " " << v.z << endl; - mOutput << " vertex " << v.x << " " << v.y << " " << v.z << endl; - mOutput << " vertex " << v.x << " " << v.y << " " << v.z << endl; - } + if (nullptr == mesh) { + continue; + } + + for (unsigned int a = 0; a < mesh->mNumVertices; ++a) { + const aiVector3D& v = mesh->mVertices[a]; + mOutput << " vertex " << v.x << " " << v.y << " " << v.z << endl; + mOutput << " vertex " << v.x << " " << v.y << " " << v.z << endl; + mOutput << " vertex " << v.x << " " << v.y << " " << v.z << endl; } } mOutput << "endsolid " << name << endl; @@ -163,7 +165,7 @@ STLExporter::STLExporter(const char* _filename, const aiScene* pScene, bool expo } // ------------------------------------------------------------------------------------------------ -void STLExporter :: WriteMesh(const aiMesh* m) +void STLExporter::WriteMesh(const aiMesh* m) { for (unsigned int i = 0; i < m->mNumFaces; ++i) { const aiFace& f = m->mFaces[i]; diff --git a/code/STLExporter.h b/code/STLExporter.h index a1d306944..51a440de7 100644 --- a/code/STLExporter.h +++ b/code/STLExporter.h @@ -52,8 +52,7 @@ struct aiScene; struct aiNode; struct aiMesh; -namespace Assimp -{ +namespace Assimp { // ------------------------------------------------------------------------------------------------ /** Helper class to export a given scene to a STL file. */ diff --git a/test/unit/utPLYImportExport.cpp b/test/unit/utPLYImportExport.cpp index c009bda39..5aabe0805 100644 --- a/test/unit/utPLYImportExport.cpp +++ b/test/unit/utPLYImportExport.cpp @@ -138,18 +138,19 @@ TEST_F( utPLYImportExport, vertexColorTest ) { EXPECT_EQ(2u, first_face.mIndices[2]); } -//Test issue #623, PLY importer should not automatically create faces +// Test issue #623, PLY importer should not automatically create faces TEST_F(utPLYImportExport, pointcloudTest) { - Assimp::Importer importer; - //Could not use aiProcess_ValidateDataStructure since it's missing faces. - const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/issue623.ply", 0); - EXPECT_NE(nullptr, scene); + Assimp::Importer importer; - EXPECT_EQ(1u, scene->mNumMeshes); - EXPECT_NE(nullptr, scene->mMeshes[0]); - EXPECT_EQ(24u, scene->mMeshes[0]->mNumVertices); - EXPECT_EQ(aiPrimitiveType::aiPrimitiveType_POINT, scene->mMeshes[0]->mPrimitiveTypes); - EXPECT_EQ(0u, scene->mMeshes[0]->mNumFaces); + //Could not use aiProcess_ValidateDataStructure since it's missing faces. + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/issue623.ply", 0); + EXPECT_NE(nullptr, scene); + + EXPECT_EQ(1u, scene->mNumMeshes); + EXPECT_NE(nullptr, scene->mMeshes[0]); + EXPECT_EQ(24u, scene->mMeshes[0]->mNumVertices); + EXPECT_EQ(aiPrimitiveType::aiPrimitiveType_POINT, scene->mMeshes[0]->mPrimitiveTypes); + EXPECT_EQ(0u, scene->mMeshes[0]->mNumFaces); } static const char *test_file = diff --git a/test/unit/utSTLImportExport.cpp b/test/unit/utSTLImportExport.cpp index 0cb9f73ee..aad6b0fa1 100644 --- a/test/unit/utSTLImportExport.cpp +++ b/test/unit/utSTLImportExport.cpp @@ -47,6 +47,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include +#include + +#include using namespace Assimp; @@ -68,3 +72,60 @@ TEST_F( utSTLImporterExporter, test_with_two_solids ) { const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/STL/triangle_with_two_solids.stl", aiProcess_ValidateDataStructure ); EXPECT_NE( nullptr, scene ); } + +#ifndef ASSIMP_BUILD_NO_EXPORT + +TEST_F(utSTLImporterExporter, test_export_pointclouds) { + struct XYZ { + float x, y, z; + }; + + std::vector points; + + for (size_t i = 0; i < 10; ++i) { + XYZ current; + current.x = static_cast(i); + current.y = static_cast(i); + current.z = static_cast(i); + points.push_back(current); + } + aiScene scene; + scene.mRootNode = new aiNode(); + + scene.mMeshes = new aiMesh*[1]; + scene.mMeshes[0] = nullptr; + scene.mNumMeshes = 1; + + scene.mMaterials = new aiMaterial*[1]; + scene.mMaterials[0] = nullptr; + scene.mNumMaterials = 1; + + scene.mMaterials[0] = new aiMaterial(); + + scene.mMeshes[0] = new aiMesh(); + scene.mMeshes[0]->mMaterialIndex = 0; + + scene.mRootNode->mMeshes = new unsigned int[1]; + scene.mRootNode->mMeshes[0] = 0; + scene.mRootNode->mNumMeshes = 1; + + auto pMesh = scene.mMeshes[0]; + + long numValidPoints = points.size(); + + pMesh->mVertices = new aiVector3D[numValidPoints]; + pMesh->mNumVertices = numValidPoints; + + int i = 0; + for (XYZ &p : points) { + pMesh->mVertices[i] = aiVector3D(p.x, p.y, p.z); + ++i; + } + + Assimp::Exporter mAiExporter; + ExportProperties *properties = new ExportProperties; + properties->SetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS, true); + mAiExporter.Export(&scene, "stl", "testExport.stl", 0, properties ); +} + +#endif From eced86b949c8c1a9fc2b74eae531b8b9b456cf68 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 1 May 2018 13:41:39 +0200 Subject: [PATCH 183/278] some refactorings. --- code/STLExporter.cpp | 50 +++++++++++++++++++++++++------------------- code/STLExporter.h | 2 +- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/code/STLExporter.cpp b/code/STLExporter.cpp index dd4df9212..7b38125ef 100644 --- a/code/STLExporter.cpp +++ b/code/STLExporter.cpp @@ -100,6 +100,8 @@ void ExportSceneSTLBinary(const char* pFile,IOSystem* pIOSystem, const aiScene* } // end of namespace Assimp +static const char *SolidToken = "solid"; +static const char *EndSolidToken = "endsolid"; // ------------------------------------------------------------------------------------------------ STLExporter::STLExporter(const char* _filename, const aiScene* pScene, bool exportPointClouds, bool binary) @@ -132,38 +134,44 @@ STLExporter::STLExporter(const char* _filename, const aiScene* pScene, bool expo WriteMeshBinary(pScene->mMeshes[i]); } } else { - const std::string& name = "AssimpScene"; // Exporting only point clouds if (exportPointClouds) { - mOutput << "solid " << name << endl; - aiVector3D nor; - mOutput << " facet normal " << nor.x << " " << nor.y << " " << nor.z << endl; - for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { - aiMesh *mesh = pScene->mMeshes[i]; - if (nullptr == mesh) { - continue; - } - - for (unsigned int a = 0; a < mesh->mNumVertices; ++a) { - const aiVector3D& v = mesh->mVertices[a]; - mOutput << " vertex " << v.x << " " << v.y << " " << v.z << endl; - mOutput << " vertex " << v.x << " " << v.y << " " << v.z << endl; - mOutput << " vertex " << v.x << " " << v.y << " " << v.z << endl; - } - } - mOutput << "endsolid " << name << endl; + WritePointCloud("Assimp_Pointcloud", pScene ); return; } - mOutput << "solid " << name << endl; + // Export the assimp mesh + const std::string name = "AssimpScene"; + mOutput << SolidToken << name << endl; for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) { - WriteMesh(pScene->mMeshes[i]); + WriteMesh(pScene->mMeshes[ i ]); } - mOutput << "endsolid " << name << endl; + mOutput << EndSolidToken << name << endl; } } +// ------------------------------------------------------------------------------------------------ +void STLExporter::WritePointCloud(const std::string &name, const aiScene* pScene) { + mOutput << " " << SolidToken << " " << name << endl; + aiVector3D nor; + mOutput << " facet normal " << nor.x << " " << nor.y << " " << nor.z << endl; + for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { + aiMesh *mesh = pScene->mMeshes[i]; + if (nullptr == mesh) { + continue; + } + + for (unsigned int a = 0; a < mesh->mNumVertices; ++a) { + const aiVector3D& v = mesh->mVertices[a]; + mOutput << " vertex " << v.x << " " << v.y << " " << v.z << endl; + mOutput << " vertex " << v.x << " " << v.y << " " << v.z << endl; + mOutput << " vertex " << v.x << " " << v.y << " " << v.z << endl; + } + } + mOutput << EndSolidToken << name << endl; +} + // ------------------------------------------------------------------------------------------------ void STLExporter::WriteMesh(const aiMesh* m) { diff --git a/code/STLExporter.h b/code/STLExporter.h index 51a440de7..6e8f90915 100644 --- a/code/STLExporter.h +++ b/code/STLExporter.h @@ -67,7 +67,7 @@ public: std::ostringstream mOutput; private: - + void WritePointCloud(const std::string &name, const aiScene* pScene); void WriteMesh(const aiMesh* m); void WriteMeshBinary(const aiMesh* m); From 037a213bb4cd1e5853df390b4a64d663efde2fe2 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 1 May 2018 15:06:56 +0200 Subject: [PATCH 184/278] STL-Exporter: fix division by zero in normalize method during update --- code/Exporter.cpp | 5 ++-- code/STLExporter.cpp | 8 +++--- include/assimp/Exporter.hpp | 8 +++++- include/assimp/GenericProperty.h | 48 ++++++++++++++++++-------------- test/unit/utSTLImportExport.cpp | 13 +++++++++ 5 files changed, 53 insertions(+), 29 deletions(-) diff --git a/code/Exporter.cpp b/code/Exporter.cpp index 53a623ecd..bd533f3b3 100644 --- a/code/Exporter.cpp +++ b/code/Exporter.cpp @@ -477,7 +477,7 @@ size_t Exporter::GetExportFormatCount() const { // ------------------------------------------------------------------------------------------------ const aiExportFormatDesc* Exporter::GetExportFormatDescription( size_t index ) const { if (index >= GetExportFormatCount()) { - return NULL; + return nullptr; } // Return from static storage if the requested index is built-in. @@ -539,8 +539,7 @@ bool ExportProperties::SetPropertyFloat(const char* szName, ai_real iValue) { // ------------------------------------------------------------------------------------------------ // Set a configuration property -bool ExportProperties :: SetPropertyString(const char* szName, const std::string& value) -{ +bool ExportProperties::SetPropertyString(const char* szName, const std::string& value) { return SetGenericProperty(mStringProperties, szName,value); } diff --git a/code/STLExporter.cpp b/code/STLExporter.cpp index 7b38125ef..e4a1dbb66 100644 --- a/code/STLExporter.cpp +++ b/code/STLExporter.cpp @@ -143,7 +143,7 @@ STLExporter::STLExporter(const char* _filename, const aiScene* pScene, bool expo // Export the assimp mesh const std::string name = "AssimpScene"; - mOutput << SolidToken << name << endl; + mOutput << SolidToken << " " << name << endl; for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) { WriteMesh(pScene->mMeshes[ i ]); } @@ -169,7 +169,7 @@ void STLExporter::WritePointCloud(const std::string &name, const aiScene* pScene mOutput << " vertex " << v.x << " " << v.y << " " << v.z << endl; } } - mOutput << EndSolidToken << name << endl; + mOutput << EndSolidToken << " " << name << endl; } // ------------------------------------------------------------------------------------------------ @@ -185,7 +185,7 @@ void STLExporter::WriteMesh(const aiMesh* m) for(unsigned int a = 0; a < f.mNumIndices; ++a) { nor += m->mNormals[f.mIndices[a]]; } - nor.Normalize(); + nor.NormalizeSafe(); } mOutput << " facet normal " << nor.x << " " << nor.y << " " << nor.z << endl; mOutput << " outer loop" << endl; @@ -199,7 +199,7 @@ void STLExporter::WriteMesh(const aiMesh* m) } } -void STLExporter :: WriteMeshBinary(const aiMesh* m) +void STLExporter::WriteMeshBinary(const aiMesh* m) { for (unsigned int i = 0; i < m->mNumFaces; ++i) { const aiFace& f = m->mFaces[i]; diff --git a/include/assimp/Exporter.hpp b/include/assimp/Exporter.hpp index dfbac9371..3d1a9ea85 100644 --- a/include/assimp/Exporter.hpp +++ b/include/assimp/Exporter.hpp @@ -115,8 +115,14 @@ public: } }; -public: + /** + * @brief The class constructor. + */ Exporter(); + + /** + * @brief The class destructor. + */ ~Exporter(); // ------------------------------------------------------------------- diff --git a/include/assimp/GenericProperty.h b/include/assimp/GenericProperty.h index 96c74b4c4..7b75cb1c8 100644 --- a/include/assimp/GenericProperty.h +++ b/include/assimp/GenericProperty.h @@ -46,15 +46,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "Hash.h" -#include +#include // ------------------------------------------------------------------------------------------------ template -inline bool SetGenericProperty(std::map< unsigned int, T >& list, - const char* szName, const T& value) -{ - ai_assert(NULL != szName); +inline +bool SetGenericProperty(std::map< unsigned int, T >& list, + const char* szName, const T& value) { + ai_assert(nullptr != szName); const uint32_t hash = SuperFastHash(szName); typename std::map::iterator it = list.find(hash); @@ -63,20 +63,22 @@ inline bool SetGenericProperty(std::map< unsigned int, T >& list, return false; } (*it).second = value; + return true; } // ------------------------------------------------------------------------------------------------ template -inline const T& GetGenericProperty(const std::map< unsigned int, T >& list, - const char* szName, const T& errorReturn) -{ - ai_assert(NULL != szName); +inline +const T& GetGenericProperty(const std::map< unsigned int, T >& list, + const char* szName, const T& errorReturn) { + ai_assert(nullptr != szName); const uint32_t hash = SuperFastHash(szName); typename std::map::const_iterator it = list.find(hash); - if (it == list.end()) + if (it == list.end()) { return errorReturn; + } return (*it).second; } @@ -85,16 +87,17 @@ inline const T& GetGenericProperty(const std::map< unsigned int, T >& list, // Special version for pointer types - they will be deleted when replaced with another value // passing NULL removes the whole property template -inline void SetGenericPropertyPtr(std::map< unsigned int, T* >& list, - const char* szName, T* value, bool* bWasExisting = NULL) -{ - ai_assert(NULL != szName); +inline +void SetGenericPropertyPtr(std::map< unsigned int, T* >& list, + const char* szName, T* value, bool* bWasExisting = nullptr ) { + ai_assert(nullptr != szName); const uint32_t hash = SuperFastHash(szName); typename std::map::iterator it = list.find(hash); if (it == list.end()) { - if (bWasExisting) + if (bWasExisting) { *bWasExisting = false; + } list.insert(std::pair( hash, value )); return; @@ -106,20 +109,23 @@ inline void SetGenericPropertyPtr(std::map< unsigned int, T* >& list, if (!value) { list.erase(it); } - if (bWasExisting) + if (bWasExisting) { *bWasExisting = true; + } } // ------------------------------------------------------------------------------------------------ template -inline bool HasGenericProperty(const std::map< unsigned int, T >& list, - const char* szName) -{ - ai_assert(NULL != szName); +inline +bool HasGenericProperty(const std::map< unsigned int, T >& list, + const char* szName) { + ai_assert(nullptr != szName); const uint32_t hash = SuperFastHash(szName); typename std::map::const_iterator it = list.find(hash); - if (it == list.end()) return false; + if (it == list.end()) { + return false; + } return true; } diff --git a/test/unit/utSTLImportExport.cpp b/test/unit/utSTLImportExport.cpp index aad6b0fa1..be73c5421 100644 --- a/test/unit/utSTLImportExport.cpp +++ b/test/unit/utSTLImportExport.cpp @@ -75,6 +75,17 @@ TEST_F( utSTLImporterExporter, test_with_two_solids ) { #ifndef ASSIMP_BUILD_NO_EXPORT +TEST_F(utSTLImporterExporter, exporterTest) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/STL/Spider_ascii.stl", aiProcess_ValidateDataStructure); + + Assimp::Exporter mAiExporter; + mAiExporter.Export( scene, "stl", "spiderExport.stl" ); + + const aiScene *scene2 = importer.ReadFile("spiderExport.stl", aiProcess_ValidateDataStructure); + //EXPECT_NE(nullptr, scene2); +} + TEST_F(utSTLImporterExporter, test_export_pointclouds) { struct XYZ { float x, y, z; @@ -126,6 +137,8 @@ TEST_F(utSTLImporterExporter, test_export_pointclouds) { ExportProperties *properties = new ExportProperties; properties->SetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS, true); mAiExporter.Export(&scene, "stl", "testExport.stl", 0, properties ); + + delete properties; } #endif From 1679c8b08e9186133dd9bdea5cc26e7548fd8a68 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 1 May 2018 16:03:56 +0200 Subject: [PATCH 185/278] STL: reenable unittest. --- test/unit/utSTLImportExport.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/utSTLImportExport.cpp b/test/unit/utSTLImportExport.cpp index be73c5421..181862560 100644 --- a/test/unit/utSTLImportExport.cpp +++ b/test/unit/utSTLImportExport.cpp @@ -83,7 +83,7 @@ TEST_F(utSTLImporterExporter, exporterTest) { mAiExporter.Export( scene, "stl", "spiderExport.stl" ); const aiScene *scene2 = importer.ReadFile("spiderExport.stl", aiProcess_ValidateDataStructure); - //EXPECT_NE(nullptr, scene2); + EXPECT_NE(nullptr, scene2); } TEST_F(utSTLImporterExporter, test_export_pointclouds) { From ed860230169d4c0ed2d7fa2a303b190da4b07c20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Fricoteaux?= Date: Wed, 2 May 2018 16:13:17 +0200 Subject: [PATCH 186/278] Change glTF2 file extensions from gltf2/glb2 to gltf/glb in the exporter so that it matches the importer and respect the standard specifications --- code/Exporter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/Exporter.cpp b/code/Exporter.cpp index bd533f3b3..894c00740 100644 --- a/code/Exporter.cpp +++ b/code/Exporter.cpp @@ -154,9 +154,9 @@ Exporter::ExportFormatEntry gExporters[] = aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ), Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB, aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ), - Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf2", &ExportSceneGLTF2, + Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf", &ExportSceneGLTF2, aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ), - Exporter::ExportFormatEntry( "glb2", "GL Transmission Format v. 2 (binary)", "glb2", &ExportSceneGLB2, + Exporter::ExportFormatEntry( "glb2", "GL Transmission Format v. 2 (binary)", "glb", &ExportSceneGLB2, aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ), #endif From a0bf664695dd9a4ec46b7a136cdef2003d690056 Mon Sep 17 00:00:00 2001 From: kimkulling Date: Wed, 2 May 2018 16:42:22 +0200 Subject: [PATCH 187/278] closes code/SortByPTypeProcess.cpp: fix memory leak. --- code/SortByPTypeProcess.cpp | 41 +++++++++++++++---------------------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/code/SortByPTypeProcess.cpp b/code/SortByPTypeProcess.cpp index ee18585e2..b67da5b95 100644 --- a/code/SortByPTypeProcess.cpp +++ b/code/SortByPTypeProcess.cpp @@ -85,8 +85,6 @@ void SortByPTypeProcess::SetupProperties(const Importer* pImp) // Update changed meshes in all nodes void UpdateNodes(const std::vector& replaceMeshIndex, aiNode* node) { -// std::vector::const_iterator it; - if (node->mNumMeshes) { unsigned int newSize = 0; @@ -133,10 +131,8 @@ void UpdateNodes(const std::vector& replaceMeshIndex, aiNode* node // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void SortByPTypeProcess::Execute( aiScene* pScene) -{ - if (!pScene->mNumMeshes) - { +void SortByPTypeProcess::Execute( aiScene* pScene) { + if ( 0 == pScene->mNumMeshes) { ASSIMP_LOG_DEBUG("SortByPTypeProcess skipped, there are no meshes"); return; } @@ -152,42 +148,38 @@ void SortByPTypeProcess::Execute( aiScene* pScene) std::vector replaceMeshIndex(pScene->mNumMeshes*4,UINT_MAX); std::vector::iterator meshIdx = replaceMeshIndex.begin(); - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - { + for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { aiMesh* const mesh = pScene->mMeshes[i]; ai_assert(0 != mesh->mPrimitiveTypes); // if there's just one primitive type in the mesh there's nothing to do for us unsigned int num = 0; - if (mesh->mPrimitiveTypes & aiPrimitiveType_POINT) - { + if (mesh->mPrimitiveTypes & aiPrimitiveType_POINT) { ++aiNumMeshesPerPType[0]; ++num; } - if (mesh->mPrimitiveTypes & aiPrimitiveType_LINE) - { + if (mesh->mPrimitiveTypes & aiPrimitiveType_LINE) { ++aiNumMeshesPerPType[1]; ++num; } - if (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE) - { + if (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE) { ++aiNumMeshesPerPType[2]; ++num; } - if (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON) - { + if (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON) { ++aiNumMeshesPerPType[3]; ++num; } - if (1 == num) - { - if (!(configRemoveMeshes & mesh->mPrimitiveTypes)) - { - *meshIdx = (unsigned int) outMeshes.size(); + if (1 == num) { + if (!(configRemoveMeshes & mesh->mPrimitiveTypes)) { + *meshIdx = static_cast( outMeshes.size() ); outMeshes.push_back(mesh); + } else { + delete mesh; + pScene->mMeshes[ i ] = nullptr; + bAnyChanges = true; } - else bAnyChanges = true; meshIdx += 4; continue; @@ -195,14 +187,13 @@ void SortByPTypeProcess::Execute( aiScene* pScene) bAnyChanges = true; // reuse our current mesh arrays for the submesh - // with the largest numer of primitives + // with the largest number of primitives unsigned int aiNumPerPType[4] = {0,0,0,0}; aiFace* pFirstFace = mesh->mFaces; aiFace* const pLastFace = pFirstFace + mesh->mNumFaces; unsigned int numPolyVerts = 0; - for (;pFirstFace != pLastFace; ++pFirstFace) - { + for (;pFirstFace != pLastFace; ++pFirstFace) { if (pFirstFace->mNumIndices <= 3) ++aiNumPerPType[pFirstFace->mNumIndices-1]; else From 4aaf7ad5474c14affaa4d6971d7a9ff6c538173b Mon Sep 17 00:00:00 2001 From: Alexis Breust Date: Thu, 3 May 2018 11:07:39 +0200 Subject: [PATCH 188/278] Added name to nodes --- code/glTF2Exporter.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index fcf8005ae..bd33848d9 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -759,7 +759,7 @@ void glTF2Exporter::ExportMeshes() if (c) p.attributes.color.push_back(c); } - + /*************** Vertices indices ****************/ if (aim->mNumFaces > 0) { std::vector indices; @@ -891,6 +891,8 @@ unsigned int glTF2Exporter::ExportNodeHierarchy(const aiNode* n) { Ref node = mAsset->nodes.Create(mAsset->FindUniqueID(n->mName.C_Str(), "node")); + node->name = n->mName.C_Str(); + if (!n->mTransformation.IsIdentity()) { node->matrix.isPresent = true; CopyValue(n->mTransformation, node->matrix.value); From 458a7ae80174ae6a1d8631d1694f070acabb49ce Mon Sep 17 00:00:00 2001 From: Nicholas Woodfield Date: Thu, 3 May 2018 14:59:18 -0400 Subject: [PATCH 189/278] Silencing compile warnings during build, all little stuff like uint to size_t or BOOL to bool. --- code/D3MFImporter.cpp | 4 ++-- code/DefaultIOSystem.cpp | 6 +++--- code/glTF2Exporter.cpp | 6 +++--- include/assimp/metadata.h | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index 0a3a140f3..e02c5f41d 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -115,10 +115,10 @@ public: // import the metadata if ( !mMetaData.empty() ) { const size_t numMeta( mMetaData.size() ); - scene->mMetaData = aiMetadata::Alloc( numMeta ); + scene->mMetaData = aiMetadata::Alloc(static_cast( numMeta ) ); for ( size_t i = 0; i < numMeta; ++i ) { aiString val( mMetaData[ i ].value ); - scene->mMetaData->Set( i, mMetaData[ i ].name, val ); + scene->mMetaData->Set(static_cast( i ), mMetaData[ i ].name, val ); } } diff --git a/code/DefaultIOSystem.cpp b/code/DefaultIOSystem.cpp index fee9c3e7f..afa95d364 100644 --- a/code/DefaultIOSystem.cpp +++ b/code/DefaultIOSystem.cpp @@ -76,7 +76,7 @@ bool DefaultIOSystem::Exists( const char* pFile) const #ifdef _WIN32 wchar_t fileName16[PATHLIMIT]; - bool isUnicode = IsTextUnicode(pFile, static_cast(strlen(pFile)), NULL); + bool isUnicode = IsTextUnicode(pFile, static_cast(strlen(pFile)), NULL) != 0; if (isUnicode) { MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, pFile, -1, fileName16, PATHLIMIT); @@ -110,7 +110,7 @@ IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode) FILE* file; #ifdef _WIN32 wchar_t fileName16[PATHLIMIT]; - bool isUnicode = IsTextUnicode(strFile, static_cast(strlen(strFile)), NULL ); + bool isUnicode = IsTextUnicode(strFile, static_cast(strlen(strFile)), NULL) != 0; if (isUnicode) { MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, strFile, -1, fileName16, PATHLIMIT); std::string mode8(strMode); @@ -158,7 +158,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out) { ai_assert(in && _out); #if defined( _MSC_VER ) || defined( __MINGW32__ ) - bool isUnicode = IsTextUnicode(in, static_cast(strlen(in)), NULL); + bool isUnicode = IsTextUnicode(in, static_cast(strlen(in)), NULL) != 0; if (isUnicode) { wchar_t out16[PATHLIMIT]; wchar_t in16[PATHLIMIT]; diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index bd33848d9..5376788b2 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -638,11 +638,11 @@ void ExportSkin(Asset& mAsset, const aiMesh* aimesh, Ref& meshRef, Refprimitives.back(); Ref vertexJointAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, vertexJointData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT); if ( vertexJointAccessor ) { - unsigned int offset = vertexJointAccessor->bufferView->byteOffset; - unsigned int bytesLen = vertexJointAccessor->bufferView->byteLength; + size_t offset = vertexJointAccessor->bufferView->byteOffset; + size_t bytesLen = vertexJointAccessor->bufferView->byteLength; unsigned int s_bytesPerComp= ComponentTypeSize(ComponentType_UNSIGNED_SHORT); unsigned int bytesPerComp = ComponentTypeSize(vertexJointAccessor->componentType); - unsigned int s_bytesLen = bytesLen * s_bytesPerComp / bytesPerComp; + size_t s_bytesLen = bytesLen * s_bytesPerComp / bytesPerComp; Ref buf = vertexJointAccessor->bufferView->buffer; uint8_t* arrys = new uint8_t[s_bytesLen]; unsigned int i = 0; diff --git a/include/assimp/metadata.h b/include/assimp/metadata.h index 70a604de9..5e53cd483 100644 --- a/include/assimp/metadata.h +++ b/include/assimp/metadata.h @@ -149,7 +149,7 @@ struct aiMetadata { mValues[ i ].mType = rhs.mValues[ i ].mType; switch ( rhs.mValues[ i ].mType ) { case AI_BOOL: - mValues[ i ].mData = new bool( rhs.mValues[i].mData ); + mValues[ i ].mData = new bool( *(static_cast( rhs.mValues[i].mData )) ); break; case AI_INT32: { int32_t v; From 908ef3e44ad37c087724553943aacb86f5f3804c Mon Sep 17 00:00:00 2001 From: Eugene Barnett Date: Sat, 5 May 2018 16:57:59 -0400 Subject: [PATCH 190/278] 1740 Issue - Enabling and Disabling importers -ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT will be respected by the macro --using local variable ASSIMP_IMPORTER_ENABLED to include or exclude --an importer -Fixes individual importer ex: set(ASSIMP_BUILD_FBX_IMPORTER OFF) -ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT is cached --if assimp is a child cmake project, need to force cache --from parent project --ex: set(ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT CACHE INTERNAL FALSE) --- code/CMakeLists.txt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index d5d05db18..c8cc2fecd 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -208,8 +208,15 @@ OPTION(ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT "default value of all ASSIMP_BUILD_ # macro to add the CMake Option ADD_ASSIMP_IMPORTER_ which enables compile of loader # this way selective loaders can be compiled (reduces filesize + compile time) MACRO(ADD_ASSIMP_IMPORTER name) - OPTION(ASSIMP_BUILD_${name}_IMPORTER "build the ${name} importer" ${ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT}) - IF(ASSIMP_BUILD_${name}_IMPORTER) + IF (ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT) + set(ASSIMP_IMPORTER_ENABLED TRUE) + IF (DEFINED ASSIMP_BUILD_${name}_IMPORTER AND NOT ASSIMP_BUILD_${name}_IMPORTER) + set(ASSIMP_IMPORTER_ENABLED FALSE) + ENDIF () + ELSE () + set(ASSIMP_IMPORTER_ENABLED ${ASSIMP_BUILD_${name}_IMPORTER}) + ENDIF () + IF (ASSIMP_IMPORTER_ENABLED) LIST(APPEND ASSIMP_LOADER_SRCS ${ARGN}) SET(ASSIMP_IMPORTERS_ENABLED "${ASSIMP_IMPORTERS_ENABLED} ${name}") SET(${name}_SRCS ${ARGN}) From ce11aa51f5085e76303ad5c26318cad7a7cbbd62 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 7 May 2018 00:07:41 +0200 Subject: [PATCH 191/278] add win32-based make script. --- code/ObjFileImporter.cpp | 29 ++++++++++++----------------- tools/make/make_all_win32_x64.bat | 16 ++++++++++++++++ 2 files changed, 28 insertions(+), 17 deletions(-) create mode 100644 tools/make/make_all_win32_x64.bat diff --git a/code/ObjFileImporter.cpp b/code/ObjFileImporter.cpp index dd0733caa..cbf2363a4 100644 --- a/code/ObjFileImporter.cpp +++ b/code/ObjFileImporter.cpp @@ -76,41 +76,36 @@ using namespace std; // ------------------------------------------------------------------------------------------------ // Default constructor -ObjFileImporter::ObjFileImporter() : - m_Buffer(), - m_pRootObject( NULL ), - m_strAbsPath( "" ) -{ +ObjFileImporter::ObjFileImporter() +: m_Buffer() +, m_pRootObject( nullptr ) +, m_strAbsPath( "" ) { DefaultIOSystem io; m_strAbsPath = io.getOsSeparator(); } // ------------------------------------------------------------------------------------------------ // Destructor. -ObjFileImporter::~ObjFileImporter() -{ +ObjFileImporter::~ObjFileImporter() { delete m_pRootObject; - m_pRootObject = NULL; + m_pRootObject = nullptr; } // ------------------------------------------------------------------------------------------------ // Returns true, if file is an obj file. -bool ObjFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler , bool checkSig ) const -{ - if(!checkSig) //Check File Extension - { +bool ObjFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler , bool checkSig ) const { + if(!checkSig) { + //Check File Extension return SimpleExtensionCheck(pFile,"obj"); - } - else //Check file Header - { + } else { + // Check file Header static const char *pTokens[] = { "mtllib", "usemtl", "v ", "vt ", "vn ", "o ", "g ", "s ", "f " }; return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 9 ); } } // ------------------------------------------------------------------------------------------------ -const aiImporterDesc* ObjFileImporter::GetInfo () const -{ +const aiImporterDesc* ObjFileImporter::GetInfo () const { return &desc; } diff --git a/tools/make/make_all_win32_x64.bat b/tools/make/make_all_win32_x64.bat new file mode 100644 index 000000000..d4561df0d --- /dev/null +++ b/tools/make/make_all_win32_x64.bat @@ -0,0 +1,16 @@ +rem @echo off +call build_env_win32.bat + +set BUILD_CONFIG=release +set PLATFORM_CONFIG=x64 +set MAX_CPU_CONFIG=4 + +set CONFIG_PARAMETER=/p:Configuration="%BUILD_CONFIG%" +set PLATFORM_PARAMETER=/p:Platform="%PLATFORM_CONFIG%" +set CPU_PARAMETER=/maxcpucount:%MAX_CPU_CONFIG% +set PLATFORM_TOOLSET=/p:PlatformToolset=%PLATFORM_VER% + +pushd ..\..\ +cmake CMakeLists.txt -G "Visual Studio 15 2017 Win64" +%MSBUILD% assimp.sln %CONFIG_PARAMETER% %PLATFORM_PARAMETER% %CPU_PARAMETER% %PLATFORM_TOOLSET% +popd From 50c5f3cb581b729e7914b0825fe710009b1fe6a9 Mon Sep 17 00:00:00 2001 From: "A. Breust" Date: Mon, 7 May 2018 15:16:32 +0200 Subject: [PATCH 192/278] Fixes DXF loader false positive on FBX file A binary FBX file can have an header section `FBXHeaderVersion` which starts around the 70th byte. Therefore, the token check for DXF file was hitting true because the `SearchFileHeaderForToken` is case insensitive. We limit the scope of the token search to the first 32 bytes. --- code/DXFLoader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/DXFLoader.cpp b/code/DXFLoader.cpp index 90270bbd7..d317382dc 100644 --- a/code/DXFLoader.cpp +++ b/code/DXFLoader.cpp @@ -127,7 +127,7 @@ bool DXFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool if ( extension.empty() || checkSig ) { static const char *pTokens[] = { "SECTION", "HEADER", "ENDSEC", "BLOCKS" }; - return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 4 ); + return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 4, 32 ); } return false; From a9dcbedefb46664a09fb723465652726eb7377ee Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 7 May 2018 22:07:19 +0200 Subject: [PATCH 193/278] Make: save environment during make. --- tools/make/make_all_win32_x64.bat | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/make/make_all_win32_x64.bat b/tools/make/make_all_win32_x64.bat index d4561df0d..4a1e663e6 100644 --- a/tools/make/make_all_win32_x64.bat +++ b/tools/make/make_all_win32_x64.bat @@ -1,4 +1,5 @@ rem @echo off +setlocal call build_env_win32.bat set BUILD_CONFIG=release @@ -14,3 +15,4 @@ pushd ..\..\ cmake CMakeLists.txt -G "Visual Studio 15 2017 Win64" %MSBUILD% assimp.sln %CONFIG_PARAMETER% %PLATFORM_PARAMETER% %CPU_PARAMETER% %PLATFORM_TOOLSET% popd +endlocal From 5a5db25df62d3047029ff915dfe941317bac4125 Mon Sep 17 00:00:00 2001 From: Jean-Louis Date: Tue, 8 May 2018 00:28:53 +0200 Subject: [PATCH 194/278] Fix AssimpView build - Use std::min/max instead of min/max macro in windef.h - Use mmsytem.h instead of timeapi.h with MinGW --- tools/assimp_view/Display.cpp | 2 +- tools/assimp_view/Material.cpp | 2 +- tools/assimp_view/MessageProc.cpp | 9 +++++++-- tools/assimp_view/assimp_view.cpp | 7 ++++++- tools/assimp_view/assimp_view.h | 5 ++++- 5 files changed, 19 insertions(+), 6 deletions(-) diff --git a/tools/assimp_view/Display.cpp b/tools/assimp_view/Display.cpp index 7d986fa9c..cb3d66031 100644 --- a/tools/assimp_view/Display.cpp +++ b/tools/assimp_view/Display.cpp @@ -2251,7 +2251,7 @@ int CDisplay::RenderTextureView() const float ny = (float)sRect.bottom; const float x = (float)sDesc.Width; const float y = (float)sDesc.Height; - float f = min((nx-30) / x,(ny-30) / y) * (m_fTextureZoom/1000.0f); + float f = std::min((nx-30) / x,(ny-30) / y) * (m_fTextureZoom/1000.0f); float fHalfX = (nx - (f * x)) / 2.0f; float fHalfY = (ny - (f * y)) / 2.0f; diff --git a/tools/assimp_view/Material.cpp b/tools/assimp_view/Material.cpp index f04ea28eb..1fb13f5a8 100644 --- a/tools/assimp_view/Material.cpp +++ b/tools/assimp_view/Material.cpp @@ -275,7 +275,7 @@ bool CMaterialManager::TryLongerPath(char* szTemp,aiString* p_szString) for (unsigned int i = 0; i < iSizeFound;++i) info.cFileName[i] = (CHAR)tolower(info.cFileName[i]); - if (0 == memcmp(info.cFileName,szFile2, min(iSizeFound,iSize))) + if (0 == memcmp(info.cFileName,szFile2, std::min(iSizeFound,iSize))) { // we have it. Build the full path ... char* sz = strrchr(szTempB,'*'); diff --git a/tools/assimp_view/MessageProc.cpp b/tools/assimp_view/MessageProc.cpp index 71bc5c8bb..88a01fd02 100644 --- a/tools/assimp_view/MessageProc.cpp +++ b/tools/assimp_view/MessageProc.cpp @@ -45,7 +45,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include + +#ifdef __MINGW32__ +#include +#else #include +#endif namespace AssimpView { @@ -1050,9 +1055,9 @@ void DoExport(size_t formatId) ai_assert(strlen(szFileName) <= MAX_PATH); // invent a nice default file name - char* sz = max(strrchr(szFileName,'\\'),strrchr(szFileName,'/')); + char* sz = std::max(strrchr(szFileName,'\\'),strrchr(szFileName,'/')); if (sz) { - strncpy(sz,max(strrchr(g_szFileName,'\\'),strrchr(g_szFileName,'/')),MAX_PATH); + strncpy(sz,std::max(strrchr(g_szFileName,'\\'),strrchr(g_szFileName,'/')),MAX_PATH); } } else { diff --git a/tools/assimp_view/assimp_view.cpp b/tools/assimp_view/assimp_view.cpp index e68b20a00..4d7850cd5 100644 --- a/tools/assimp_view/assimp_view.cpp +++ b/tools/assimp_view/assimp_view.cpp @@ -43,10 +43,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "assimp_view.h" -#include #include #include +#ifdef __MINGW32__ +#include +#else +#include +#endif + using namespace std; namespace AssimpView { diff --git a/tools/assimp_view/assimp_view.h b/tools/assimp_view/assimp_view.h index 70bce2ce4..9317495c1 100644 --- a/tools/assimp_view/assimp_view.h +++ b/tools/assimp_view/assimp_view.h @@ -46,6 +46,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_SHADER_COMPILE_FLAGS D3DXSHADER_USE_LEGACY_D3DX9_31_DLL +// Because Dx headers include windef.h with min/max redefinition +#define NOMINMAX + // include resource definitions #include "resource.h" @@ -177,7 +180,7 @@ type clamp(intype in) { // for unsigned types only ... intype mask = (0x1u << (sizeof(type)*8))-1; - return (type)max((intype)0,min(in,mask)); + return (type)std::max((intype)0,std::min(in,mask)); } From 8d42b31e20136cb8779f1bffef5ce7744f36b084 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 8 May 2018 09:46:32 +0200 Subject: [PATCH 195/278] Update metadata.h Replace type pronning by a simple memcpy operation. --- include/assimp/metadata.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/assimp/metadata.h b/include/assimp/metadata.h index 5e53cd483..8ac8e250a 100644 --- a/include/assimp/metadata.h +++ b/include/assimp/metadata.h @@ -149,7 +149,8 @@ struct aiMetadata { mValues[ i ].mType = rhs.mValues[ i ].mType; switch ( rhs.mValues[ i ].mType ) { case AI_BOOL: - mValues[ i ].mData = new bool( *(static_cast( rhs.mValues[i].mData )) ); + mValues[ i ].mData = new bool; + ::memcpy( mValues[ i ].mData, rhs.mValues[ i ].mData, sizeof(bool) ); break; case AI_INT32: { int32_t v; From 700c85bbfbc1de7a7776cd0082ed993e445a7db3 Mon Sep 17 00:00:00 2001 From: Diego Lopes Date: Tue, 8 May 2018 13:01:56 -0400 Subject: [PATCH 196/278] _stat64 doesn't seem to exist. use __stat64! Merely add an extra _ to the type name... --- code/DefaultIOSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/DefaultIOSystem.cpp b/code/DefaultIOSystem.cpp index afa95d364..58afe475c 100644 --- a/code/DefaultIOSystem.cpp +++ b/code/DefaultIOSystem.cpp @@ -80,7 +80,7 @@ bool DefaultIOSystem::Exists( const char* pFile) const if (isUnicode) { MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, pFile, -1, fileName16, PATHLIMIT); - struct _stat64 filestat; + struct __stat64 filestat; if (0 != _wstat64(fileName16, &filestat)) { return false; } From 60d803f49050344f761010ac91750aa5ce67531d Mon Sep 17 00:00:00 2001 From: kimkulling Date: Wed, 9 May 2018 09:51:05 +0200 Subject: [PATCH 197/278] Some minor fixes of typos and formatting issues. --- tools/assimp_view/AnimEvaluator.cpp | 3 +- tools/assimp_view/Display.cpp | 24 ++-- tools/assimp_view/MessageProc.cpp | 31 ++--- tools/assimp_view/assimp_view.cpp | 8 +- tools/assimp_view/assimp_view.rc | 169 ++++++++++++---------------- 5 files changed, 102 insertions(+), 133 deletions(-) diff --git a/tools/assimp_view/AnimEvaluator.cpp b/tools/assimp_view/AnimEvaluator.cpp index 0d6c7c75a..94c581df4 100644 --- a/tools/assimp_view/AnimEvaluator.cpp +++ b/tools/assimp_view/AnimEvaluator.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2015, assimp team +Copyright (c) 2006-2018, assimp team All rights reserved. @@ -40,6 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "assimp_view.h" + #include using namespace AssimpView; diff --git a/tools/assimp_view/Display.cpp b/tools/assimp_view/Display.cpp index 7d986fa9c..207c26fa9 100644 --- a/tools/assimp_view/Display.cpp +++ b/tools/assimp_view/Display.cpp @@ -96,8 +96,9 @@ D3DXVECTOR4 g_aclNormalColors[14] = void GetNodeCount(aiNode* pcNode, unsigned int* piCnt) { *piCnt = *piCnt+1; - for (unsigned int i = 0; i < pcNode->mNumChildren;++i) - GetNodeCount(pcNode->mChildren[i],piCnt); + for (unsigned int i = 0; i < pcNode->mNumChildren; ++i) { + GetNodeCount(pcNode->mChildren[i], piCnt); + } } //------------------------------------------------------------------------------- @@ -1042,16 +1043,23 @@ int CDisplay::OnSetupTextureView(TextureInfo* pcNew) switch (pcNew->eOp) { case aiTextureOp_Add: - szOp = "add";break; + szOp = "add"; + break; case aiTextureOp_Subtract: - szOp = "sub";break; + szOp = "sub"; + break; case aiTextureOp_Divide: - szOp = "div";break; + szOp = "div"; + break; case aiTextureOp_SignedAdd: - szOp = "addsign";break; + szOp = "addsign"; + break; case aiTextureOp_SmoothAdd: - szOp = "addsmooth";break; - default: szOp = "mul"; + szOp = "addsmooth"; + break; + default: + szOp = "mul"; + break; }; SetWindowText(GetDlgItem(g_hDlg,IDC_ELOAD),szOp); diff --git a/tools/assimp_view/MessageProc.cpp b/tools/assimp_view/MessageProc.cpp index 71bc5c8bb..695e8cfd6 100644 --- a/tools/assimp_view/MessageProc.cpp +++ b/tools/assimp_view/MessageProc.cpp @@ -80,8 +80,7 @@ void SaveHistory(); // File associations are registered in HKCU\Software\Classes. They might // be overwritten by global file associations. //------------------------------------------------------------------------------- -void MakeFileAssociations() - { +void MakeFileAssociations() { char szTemp2[MAX_PATH]; char szTemp[MAX_PATH + 10]; @@ -1399,7 +1398,7 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, g_hDlg = hwndDlg; - // load the state of the usr interface + // load the state of the user interface InitUI(); // load the file history @@ -1643,11 +1642,6 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, xPos = xPos2 = sPoint.x; yPos = yPos2 = sPoint.y; - /* xPos -= 10; - yPos -= 10; - xPos2 = xPos-3; - yPos2 = yPos-5;*/ - RECT sRect; GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect); sRect.right -= sRect.left; @@ -1830,7 +1824,6 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, return TRUE; case WM_COMMAND: - HMENU hMenu = GetMenu(g_hDlg); if (ID_VIEWER_QUIT == LOWORD(wParam)) { @@ -2361,7 +2354,7 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) - { +{ UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); @@ -2371,14 +2364,13 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, // load windows common controls library to get XP style InitCommonControls(); - // intiailize the IDirect3D9 interface + // initialize the IDirect3D9 interface g_hInstance = hInstance; - if (0 == InitD3D()) - { + if (0 == InitD3D()) { MessageBox(NULL,"Failed to initialize Direct3D 9", "ASSIMP ModelViewer",MB_OK); return -6; - } + } // create the main dialog HWND hDlg = CreateDialog(hInstance,MAKEINTRESOURCE(IDD_DIALOGMAIN), @@ -2395,12 +2387,11 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, Assimp::DefaultLogger::Debugging | Assimp::DefaultLogger::Info | Assimp::DefaultLogger::Err | Assimp::DefaultLogger::Warn); - if (NULL == hDlg) - { + if (NULL == hDlg) { MessageBox(NULL,"Failed to create dialog from resource", "ASSIMP ModelViewer",MB_OK); return -5; - } + } // display the window g_hDlg = hDlg; @@ -2410,12 +2401,12 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, UpdateWindow( hDlg ); // create the D3D device object - if (0 == CreateDevice(g_sOptions.bMultiSample,false,true)) - { + if (0 == CreateDevice(g_sOptions.bMultiSample,false,true)) { MessageBox(NULL,"Failed to initialize Direct3D 9 (2)", "ASSIMP ModelViewer",MB_OK); return -4; - } + } + CLogDisplay::Instance().AddEntry("[OK] Here we go!"); // create the log window diff --git a/tools/assimp_view/assimp_view.cpp b/tools/assimp_view/assimp_view.cpp index e68b20a00..ac2d1e66d 100644 --- a/tools/assimp_view/assimp_view.cpp +++ b/tools/assimp_view/assimp_view.cpp @@ -143,7 +143,7 @@ float g_fLoadTime = 0.0f; //------------------------------------------------------------------------------- // Entry point for the loader thread -// The laoder thread loads the asset while the progress dialog displays the +// The loader thread loads the asset while the progress dialog displays the // smart progress bar //------------------------------------------------------------------------------- DWORD WINAPI LoadThreadProc(LPVOID lpParameter) @@ -200,9 +200,9 @@ DWORD WINAPI LoadThreadProc(LPVOID lpParameter) // load the current asset // THe path to the asset is specified in the global path variable //------------------------------------------------------------------------------- -int LoadAsset(void) +int LoadAsset() { - // set the world and world rotation matrices to the identuty + // set the world and world rotation matrices to the identity g_mWorldRotate = aiMatrix4x4(); g_mWorld = aiMatrix4x4(); @@ -1130,8 +1130,6 @@ int GetProjectionMatrix (aiMatrix4x4& p_mOut) return 1; } - -//------------------------------------------------------------------------------- //------------------------------------------------------------------------------- aiVector3D GetCameraMatrix (aiMatrix4x4& p_mOut) { diff --git a/tools/assimp_view/assimp_view.rc b/tools/assimp_view/assimp_view.rc index 093b860fc..aca323b09 100644 --- a/tools/assimp_view/assimp_view.rc +++ b/tools/assimp_view/assimp_view.rc @@ -15,13 +15,11 @@ #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// -// German (Germany) resources +// Deutsch (Deutschland) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) -#ifdef _WIN32 LANGUAGE LANG_GERMAN, SUBLANG_GERMAN #pragma code_page(1252) -#endif //_WIN32 ///////////////////////////////////////////////////////////////////////////// // @@ -32,6 +30,7 @@ LANGUAGE LANG_GERMAN, SUBLANG_GERMAN // remains consistent on all systems. IDI_ASSIMP_VIEW ICON "../shared/assimp_tools_icon.ico" + ///////////////////////////////////////////////////////////////////////////// // // Dialog @@ -49,104 +48,63 @@ BEGIN LTEXT "http://assimp.sourceforge.net http://www.zfx.info",IDC_STATIC,31,101,127,22 DEFPUSHBUTTON "Love this library",IDOK,186,110,84,14 CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,148,283,1 - CONTROL 130,IDC_STATIC,"Static",SS_BITMAP,0,129,514,20 + CONTROL IDB_BITMAP1,IDC_STATIC,"Static",SS_BITMAP,0,129,514,20 CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,10,281,1 END -#define X_GROUP1 7 -#define W_GROUP1 6+160+6 -#define X_GROUP2 X_GROUP1+W_GROUP1+7 -#define W_GROUP2 6+150+8 -#define X_GROUP3 X_GROUP2+W_GROUP2+7 -#define W_GROUP3 6+60+35+8 - -#define W X_GROUP3+W_GROUP3+47 -#define H 450 - -#define Y_PANEL H-12-82-7-7-14-4 -#define Y_GROUPS Y_PANEL+14+7 - -#define TREE_W 143 -#define COMBO_W 100 - -IDD_DIALOGMAIN DIALOGEX 0, 0, W+TREE_W, H -STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +IDD_DIALOGMAIN DIALOGEX 0, 0, 656, 450 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_ACCEPTFILES | WS_EX_WINDOWEDGE CAPTION "Open Asset Import Library - Model Viewer " MENU IDR_MENU1 FONT 8, "Microsoft Sans Serif", 400, 0, 0x0 BEGIN - - CONTROL "",IDC_RT,"Static",SS_OWNERDRAW,0,0,W,Y_PANEL - CONTROL "",IDC_TREE1,"SysTreeView32",TVS_HASBUTTONS|TVS_HASLINES|TVS_SHOWSELALWAYS|WS_BORDER|WS_HSCROLL|WS_TABSTOP, W,0,TREE_W,H - -#define Y Y_PANEL+4 - CONTROL "<<",IDC_BLUBB,"Button",BS_AUTOCHECKBOX|BS_PUSHLIKE|WS_TABSTOP, W-7-35,Y,35,14 - COMBOBOX IDC_COMBO1, W-7-35-4-100,Y,100,14, CBS_DROPDOWN|WS_VSCROLL|WS_TABSTOP - PUSHBUTTON "Play",IDC_PLAY, W-7-35-4-100-35-4,Y,35,14 - CONTROL "",IDC_SLIDERANIM,"msctls_trackbar32",TBS_AUTOTICKS|TBS_BOTH|TBS_NOTICKS|WS_TABSTOP, 0,Y,W-7-35-4-100-35-4,15 - -#undef Y -#define Y Y_GROUPS+12 -#define X X_GROUP1+6 - - GROUPBOX "Display",IDC_STATIC, X_GROUP1,Y_GROUPS,W_GROUP1,12+82+7 - - CONTROL "Multisampling [M]",IDC_TOGGLEMS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, X,Y,80,10 - CONTROL "Wireframe [W]",IDC_TOGGLEWIRE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, X,Y+12,80,10 - CONTROL "No materials [D]",IDC_TOGGLEMAT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, X,Y+24,80,10 - CONTROL "Display normals [N]",IDC_TOGGLENORMALS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, X,Y+36,80,10 - CONTROL "Low quality [P]",IDC_LOWQUALITY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, X,Y+48,80,10 - CONTROL "No specular [S]",IDC_NOSPECULAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, X,Y+60,80,10 - CONTROL "Show skeleton [K]",IDC_SHOWSKELETON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, X,Y+72,80,10 - - CONTROL "AutoRotate [A]",IDC_AUTOROTATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, X+80,Y,80,10 - CONTROL "Zoom/Rotate [Z]",IDC_ZOOM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, X+80,Y+12,80,10 - CONTROL "Rotate lights [R]",IDC_LIGHTROTATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, X+80,Y+24,80,10 - CONTROL "Two lights [L]",IDC_3LIGHTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, X+80,Y+36,80,10 - CONTROL "Backface culling [C]",IDC_BFCULL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, X+80,Y+48,80,10 - CONTROL "No transparency [T]",IDC_NOAB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, X+80,Y+60,80,10 - -#undef X -#define X X_GROUP2+6 - - GROUPBOX "Statistics",IDC_STATIC, X_GROUP2,Y_GROUPS,W_GROUP2,12+36+8+7 - - LTEXT "Vertices:",IDC_NUMVERTS, X,Y,35,8 - LTEXT "Nodes:",IDC_NUMNODES, X,Y+12,35,8 - LTEXT "Shaders:",IDC_NUMSHADERS, X,Y+24,35,8 - LTEXT "Time:",IDC_LOADTIME, X,Y+36,35,8 - - EDITTEXT IDC_EVERT, X+35,Y,35,8, ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | ES_RIGHT - EDITTEXT IDC_ENODEWND, X+35,Y+12,35,8, ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | ES_RIGHT - EDITTEXT IDC_ESHADER, X+35,Y+24,35,8, ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | ES_RIGHT - EDITTEXT IDC_ELOAD, X+35,Y+36,35,8, ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | ES_RIGHT - - LTEXT "Faces:",IDC_NUMFACES, X+80,Y,35,8 - LTEXT "Materials:",IDC_NUMMATS, X+80,Y+12,35,8 - LTEXT "Meshes:",IDC_NUMMESHES, X+80,Y+24,35,8 - LTEXT "FPS:",IDC_FPS, X+80,Y+36,35,8 - - EDITTEXT IDC_EFACE, X+115,Y,35,8, ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | ES_RIGHT - EDITTEXT IDC_EMAT, X+115,Y+12,35,8, ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | ES_RIGHT - EDITTEXT IDC_EMESH, X+115,Y+24,35,8, ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | ES_RIGHT - EDITTEXT IDC_EFPS, X+115,Y+36,35,8, ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | ES_RIGHT - - EDITTEXT IDC_VIEWMATRIX, X,Y+48+7,72,44, ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_VISIBLE - -#undef X -#define X X_GROUP3+6 - - GROUPBOX "Colors",IDC_STATIC, X_GROUP3,Y_GROUPS,W_GROUP3,12+54+14+7 - - LTEXT "Primary:",IDC_STATIC, X,Y+3,48,8 - LTEXT "Secondary:",IDC_STATIC, X,Y+3+18,54,8 - LTEXT "Ambient:",IDC_STATIC, X,Y+3+36,54,8 - - CONTROL "Button1",IDC_LCOLOR1,"Button",BS_OWNERDRAW | WS_TABSTOP, X+60,Y,35,14 - CONTROL "Button1",IDC_LCOLOR2,"Button",BS_OWNERDRAW | WS_TABSTOP, X+60,Y+18,35,14 - CONTROL "Button1",IDC_LCOLOR3,"Button",BS_OWNERDRAW | WS_TABSTOP, X+60,Y+36,35,14 - PUSHBUTTON "Reset",IDC_LRESET, X+60,Y+54,35,14 + CONTROL "",IDC_RT,"Static",SS_OWNERDRAW,0,0,513,324 + CONTROL "",IDC_TREE1,"SysTreeView32",TVS_HASBUTTONS | TVS_HASLINES | TVS_SHOWSELALWAYS | WS_BORDER | WS_HSCROLL | WS_TABSTOP,513,0,143,450 + CONTROL "<<",IDC_BLUBB,"Button",BS_AUTOCHECKBOX | BS_PUSHLIKE | WS_TABSTOP,471,328,35,14 + COMBOBOX IDC_COMBO1,367,328,100,14,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Play",IDC_PLAY,328,328,35,14 + CONTROL "",IDC_SLIDERANIM,"msctls_trackbar32",TBS_AUTOTICKS | TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,0,328,328,15 + GROUPBOX "Display",IDC_STATIC,7,345,172,101 + CONTROL "Multisampling [M]",IDC_TOGGLEMS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,357,80,10 + CONTROL "Wireframe [W]",IDC_TOGGLEWIRE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,369,80,10 + CONTROL "No materials [D]",IDC_TOGGLEMAT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,381,80,10 + CONTROL "Display normals [N]",IDC_TOGGLENORMALS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,393,80,10 + CONTROL "Low quality [P]",IDC_LOWQUALITY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,405,80,10 + CONTROL "No specular [S]",IDC_NOSPECULAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,417,80,10 + CONTROL "Show skeleton [K]",IDC_SHOWSKELETON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,429,80,10 + CONTROL "AutoRotate [A]",IDC_AUTOROTATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,357,80,10 + CONTROL "Zoom/Rotate [Z]",IDC_ZOOM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,369,80,10 + CONTROL "Rotate lights [R]",IDC_LIGHTROTATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,381,80,10 + CONTROL "Two lights [L]",IDC_3LIGHTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,393,80,10 + CONTROL "Backface culling [C]",IDC_BFCULL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,405,80,10 + CONTROL "No transparency [T]",IDC_NOAB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,417,80,10 + GROUPBOX "Statistics",IDC_STATIC,186,345,164,63 + LTEXT "Vertices:",IDC_NUMVERTS,192,357,35,8 + LTEXT "Nodes:",IDC_NUMNODES,192,369,35,8 + LTEXT "Shaders:",IDC_NUMSHADERS,192,381,35,8 + LTEXT "Time:",IDC_LOADTIME,192,393,35,8 + EDITTEXT IDC_EVERT,227,357,35,8,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER + EDITTEXT IDC_ENODEWND,227,369,35,8,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER + EDITTEXT IDC_ESHADER,227,381,35,8,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER + EDITTEXT IDC_ELOAD,227,393,35,8,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER + LTEXT "Faces:",IDC_NUMFACES,272,357,35,8 + LTEXT "Materials:",IDC_NUMMATS,272,369,35,8 + LTEXT "Meshes:",IDC_NUMMESHES,272,381,35,8 + LTEXT "FPS:",IDC_FPS,272,393,35,8 + EDITTEXT IDC_EFACE,307,357,35,8,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER + EDITTEXT IDC_EMAT,307,369,35,8,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER + EDITTEXT IDC_EMESH,307,381,35,8,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER + EDITTEXT IDC_EFPS,307,393,35,8,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER + EDITTEXT IDC_VIEWMATRIX,192,412,72,44,ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY | NOT WS_VISIBLE | NOT WS_BORDER + GROUPBOX "Colors",IDC_STATIC,357,345,109,87 + LTEXT "Primary:",IDC_STATIC,363,360,48,8 + LTEXT "Secondary:",IDC_STATIC,363,378,54,8 + LTEXT "Ambient:",IDC_STATIC,363,396,54,8 + CONTROL "Button1",IDC_LCOLOR1,"Button",BS_OWNERDRAW | WS_TABSTOP,423,357,35,14 + CONTROL "Button1",IDC_LCOLOR2,"Button",BS_OWNERDRAW | WS_TABSTOP,423,375,35,14 + CONTROL "Button1",IDC_LCOLOR3,"Button",BS_OWNERDRAW | WS_TABSTOP,423,393,35,14 + PUSHBUTTON "Reset",IDC_LRESET,423,411,35,14 END IDD_LOADDIALOG DIALOGEX 0, 0, 143, 60 @@ -268,7 +226,7 @@ END // #ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO +GUIDELINES DESIGNINFO BEGIN IDD_ABOUTBOX, DIALOG BEGIN @@ -279,7 +237,6 @@ BEGIN IDD_DIALOGMAIN, DIALOG BEGIN RIGHTMARGIN, 623 - BOTTOMMARGIN, 484 END IDD_LOADDIALOG, DIALOG @@ -321,23 +278,34 @@ END // IDB_BITMAP1 BITMAP "banner.bmp" + IDB_BANIM BITMAP "base_anim.bmp" + IDB_BDISPLAY BITMAP "base_display.bmp" + IDB_BINTER BITMAP "base_inter.bmp" + IDB_BRENDERING BITMAP "base_rendering.bmp" + IDB_BSTATS BITMAP "base_stats.bmp" + IDB_BTX BITMAP "tx.bmp" + IDB_BFX BITMAP "fx.bmp" + IDB_BNODE BITMAP "n.bmp" + IDB_BROOT BITMAP "root.bmp" + IDB_BTXI BITMAP "txi.bmp" + ///////////////////////////////////////////////////////////////////////////// // // Menu // -IDR_MENU1 MENU +IDR_MENU1 MENU BEGIN POPUP "Viewer" BEGIN @@ -424,7 +392,7 @@ BEGIN END END -IDR_TXPOPUP MENU +IDR_TXPOPUP MENU BEGIN POPUP "Hey" BEGIN @@ -437,7 +405,7 @@ BEGIN MENUITEM "This is not an easter egg", 0 END -IDR_MATPOPUP MENU +IDR_MATPOPUP MENU BEGIN POPUP "So long" BEGIN @@ -473,14 +441,17 @@ END IDR_TEXT1 TEXT "text1.bin" + ///////////////////////////////////////////////////////////////////////////// // // RCDATA // IDR_HUD RCDATA "HUD.png" + IDR_HUDMASK RCDATA "HUDMask.png" -#endif // German (Germany) resources + +#endif // Deutsch (Deutschland) resources ///////////////////////////////////////////////////////////////////////////// From d441dcd5230989581ba1bc3ebbc48cc28ed816ba Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 9 May 2018 19:15:42 +0200 Subject: [PATCH 198/278] addmissing file. --- tools/make/build_env_win32.bat | 58 ++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 tools/make/build_env_win32.bat diff --git a/tools/make/build_env_win32.bat b/tools/make/build_env_win32.bat new file mode 100644 index 000000000..cef217b70 --- /dev/null +++ b/tools/make/build_env_win32.bat @@ -0,0 +1,58 @@ +@echo off + +set "initialdir=%cd%" +goto:main + +:exitsucc +cd /d "%initialdir%" +set initialdir= + +set MSBUILD_15="C:\Program Files (x86)\Microsoft Visual Studio\2018\Professional\MSBuild\15.0\Bin\msbuild.exe" +set MSBUILD_14="C:\Program Files (x86)\MSBuild\14.0\Bin\msbuild.exe" + +if not "%VS150%"=="" set MSBUILD_15="%VS150%\MSBuild\15.0\Bin\msbuild.exe" + +if /i %VS_VERSION%==2017 ( + set MS_BUILD_EXE=%MSBUILD_15% + set PLATFORM_VER=v141 +) else ( + set MS_BUILD_EXE=%MSBUILD_14% + set PLATFORM_VER=v140 +) + +set MSBUILD=%MS_BUILD_EXE% + +exit /b 0 + +:main +if not defined PLATFORM set "PLATFORM=x64" + +::my work here is done? + +set PATH_VSWHERE=C:\Program Files (x86)\Microsoft Visual Studio\Installer\ +REM set PATH_STUDIO="C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\" + +for /f "usebackq tokens=*" %%i in (`"%PATH_VSWHERE%vswhere" -latest -products * -requires Microsoft.Component.MSBuild -property installationPath`) do ( + set InstallDir=%%i +) + +IF EXIST "%InstallDir%\VC\Auxiliary\Build\vcvarsall.bat" set VS150=%InstallDir%\ + +set "CMAKE_GENERATOR=Visual Studio 15 2017 Win64" +if not "%VS150%"=="" call "%VS150%\VC\Auxiliary\Build\vcvarsall.bat" %PLATFORM% && echo found VS 2o17 && set PLATFORM_VER=v141 && set VS_VERSION=2017 && goto:exitsucc + +set "CMAKE_GENERATOR=Visual Studio 14 2015 Win64" +if defined VS140COMNTOOLS call "%VS140COMNTOOLS%..\..\VC\vcvarsall.bat" %PLATFORM% && echo found VS 2o15 && set PLATFORM_VER=v140 && set VS_VERSION=2015 && goto:exitsucc + +if defined VS130COMNTOOLS echo call ghostbusters... found lost VS version + +set "CMAKE_GENERATOR=Visual Studio 12 2013 Win64" +if defined VS120COMNTOOLS call "%VS120COMNTOOLS%..\..\VC\vcvarsall.bat" %PLATFORM% && echo found VS 2o13 && set PLATFORM_VER=v120 && set VS_VERSION=2013 && goto:exitsucc + +set "CMAKE_GENERATOR=Visual Studio 11 2012 Win64" +if defined VS110COMNTOOLS call "%VS110COMNTOOLS%..\..\VC\vcvarsall.bat" %PLATFORM% && echo found VS 2o12 && set PLATFORM_VER=v110 && set VS_VERSION=2012 && goto:exitsucc + +set "CMAKE_GENERATOR=Visual Studio 10 2010 Win64" +if defined VS100COMNTOOLS call "%VS100COMNTOOLS%..\..\VC\vcvarsall.bat" %PLATFORM% && echo found VS 2o1o && set PLATFORM_VER=v100 && set VS_VERSION=2010 && goto:exitsucc + +goto:exitsucc \ No newline at end of file From a5a4da89008198c54095e26ee7075170a81ef59d Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 10 May 2018 09:19:53 +0200 Subject: [PATCH 199/278] Appveyor: adapt install script. --- appveyor.yml | 1 + packaging/windows-innosetup/script.iss | 38 +++++++++++++------------- tools/make/build_env_win32.bat | 1 - 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 1b87286f6..3b4b3144e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -32,6 +32,7 @@ install: - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" set CMAKE_GENERATOR_NAME=Visual Studio 15 2017 - if "%platform%"=="x64" set CMAKE_GENERATOR_NAME=%CMAKE_GENERATOR_NAME% Win64 - cmake %CMAKE_DEFINES% -G "%CMAKE_GENERATOR_NAME%" + - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" iscc packaging\windows-innosetup\script.iss cache: - code\assimp.dir\%CONFIGURATION% diff --git a/packaging/windows-innosetup/script.iss b/packaging/windows-innosetup/script.iss index f301bc4eb..8056e31ac 100644 --- a/packaging/windows-innosetup/script.iss +++ b/packaging/windows-innosetup/script.iss @@ -2,7 +2,7 @@ [Setup] AppName=Open Asset Import Library - SDK -AppVerName=Open Asset Import Library - SDK (v3.3.1) +AppVerName=Open Asset Import Library - SDK (v4.1.0) DefaultDirName={pf}\Assimp DefaultGroupName=Assimp UninstallDisplayIcon={app}\bin\x86\assimp.exe @@ -12,9 +12,9 @@ SetupIconFile=..\..\tools\shared\assimp_tools_icon.ico WizardImageFile=compiler:WizModernImage-IS.BMP WizardSmallImageFile=compiler:WizModernSmallImage-IS.BMP LicenseFile=License.rtf -OutputBaseFileName=assimp-sdk-3.3.1-setup -VersionInfoVersion=3.3.1.0 -VersionInfoTextVersion=3.3.1 +OutputBaseFileName=assimp-sdk-4.1.0-setup +VersionInfoVersion=4.1.0.0 +VersionInfoTextVersion=4.1.0 VersionInfoCompany=Assimp Development Team ArchitecturesInstallIn64BitMode=x64 @@ -35,15 +35,15 @@ Name: "dassimp"; Description: "D Bindings"; Types: full Name: "assimp_net"; Description: "C#/.NET Bindings"; Types: full [Run] -Filename: "{app}\stub\vc_redist.x86.exe"; Parameters: "/qb"; StatusMsg: "Installing VS2015 redistributable package (32 Bit)"; Check: not IsWin64 -Filename: "{app}\stub\vc_redist.x64.exe"; Parameters: "/qb"; StatusMsg: "Installing VS2015 redistributable package (64 Bit)"; Check: IsWin64 +;Filename: "{app}\stub\vc_redist.x86.exe"; Parameters: "/qb"; StatusMsg: "Installing VS2017 redistributable package (32 Bit)"; Check: not IsWin64 +Filename: "{app}\stub\vc_redist.x64.exe"; Parameters: "/qb"; StatusMsg: "Installing VS2017 redistributable package (64 Bit)"; Check: IsWin64 [Files] Source: "readme_installer.txt"; DestDir: "{app}"; Flags: isreadme ; Installer stub -Source: "vc_redist.x86.exe"; DestDir: "{app}\stub\"; Check: not IsWin64 +;Source: "vc_redist.x86.exe"; DestDir: "{app}\stub\"; Check: not IsWin64 Source: "vc_redist.x64.exe"; DestDir: "{app}\stub\"; Check: IsWin64 ; Common stuff @@ -55,18 +55,18 @@ Source: "WEB"; DestDir: "{app}" Source: "..\..\scripts\*"; DestDir: "{app}\scripts"; Flags: recursesubdirs ; x86 binaries -Source: "..\..\bin\release\x86\assimp-vc140-mt.dll"; DestDir: "{app}\bin\x86" -Source: "..\..\bin\release\x86\assimp_viewer.exe"; DestDir: "{app}\bin\x86"; Components: tools -Source: "D3DCompiler_42.dll"; DestDir: "{app}\bin\x86"; Components: tools -Source: "D3DX9_42.dll"; DestDir: "{app}\bin\x86"; Components: tools -Source: "..\..\bin\release\x86\assimp.exe"; DestDir: "{app}\bin\x86"; Components: tools +;Source: "..\..\bin\release\x86\assimp-vc140-mt.dll"; DestDir: "{app}\bin\x86" +;Source: "..\..\bin\release\x86\assimp_viewer.exe"; DestDir: "{app}\bin\x86"; Components: tools +;Source: "D3DCompiler_42.dll"; DestDir: "{app}\bin\x86"; Components: tools +;Source: "D3DX9_42.dll"; DestDir: "{app}\bin\x86"; Components: tools +;Source: "..\..\bin\release\x86\assimp.exe"; DestDir: "{app}\bin\x86"; Components: tools ; x64 binaries -Source: "..\..\bin\release\x64\assimp-vc140-mt.dll"; DestDir: "{app}\bin\x64" -Source: "..\..\bin\release\x64\assimp_viewer.exe"; DestDir: "{app}\bin\x64"; Components: tools -Source: "D3DCompiler_42_x64.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DCompiler_42.dll"; Components: tools -Source: "D3DX9_42_x64.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DX9_42.dll"; Components: tools -Source: "..\..\bin\release\x64\assimp.exe"; DestDir: "{app}\bin\x64"; Components: tools +Source: "..\..\bin\release\assimp-vc140-mt.dll"; DestDir: "{app}\bin\x64" +Source: "..\..\bin\release\assimp_viewer.exe"; DestDir: "{app}\bin\x64"; Components: tools +Source: "D3DCompiler_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DCompiler_42.dll"; Components: tools +Source: "D3DX9_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DX9_42.dll"; Components: tools +Source: "..\..\bin\release\assimp.exe"; DestDir: "{app}\bin\x64"; Components: tools ; Documentation Source: "..\..\doc\AssimpDoc_Html\AssimpDoc.chm"; DestDir: "{app}\doc"; Components: help @@ -74,8 +74,8 @@ Source: "..\..\doc\AssimpCmdDoc_Html\AssimpCmdDoc.chm"; DestDir: "{app}\doc"; Co Source: "..\..\doc\datastructure.xml"; DestDir: "{app}\doc"; Components: help ; Import libraries -Source: "..\..\lib\release\x86\assimp.lib"; DestDir: "{app}\lib\x86" -Source: "..\..\lib\release\x64\assimp.lib"; DestDir: "{app}\lib\x64" +;Source: "..\..\lib\release\x86\assimp.lib"; DestDir: "{app}\lib\x86" +Source: "..\..\lib\release\assimp-vc140-mt.lib"; DestDir: "{app}\lib\x64" ; Samples Source: "..\..\samples\*"; DestDir: "{app}\samples"; Flags: recursesubdirs; Components: samples diff --git a/tools/make/build_env_win32.bat b/tools/make/build_env_win32.bat index cef217b70..4b8b4674b 100644 --- a/tools/make/build_env_win32.bat +++ b/tools/make/build_env_win32.bat @@ -1,5 +1,4 @@ @echo off - set "initialdir=%cd%" goto:main From c08614bbff531e9e3f760595b7f0577a4dca78a0 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 10 May 2018 09:44:31 +0200 Subject: [PATCH 200/278] closes https://github.com/assimp/assimp/issues/919: add missing cast for vs2015. --- code/ColladaLoader.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/code/ColladaLoader.cpp b/code/ColladaLoader.cpp index 45dd52710..611e487b0 100644 --- a/code/ColladaLoader.cpp +++ b/code/ColladaLoader.cpp @@ -1819,9 +1819,12 @@ void ColladaLoader::ConvertPath (aiString& ss) // Maxon Cinema Collada Export writes "file:///C:\andsoon" with three slashes... // I need to filter it without destroying linux paths starting with "/somewhere" - if( ss.data[0] == '/' && isalpha( ss.data[1]) && ss.data[2] == ':' ) - { - ss.length--; +#if defined( _MSC_VER ) + if( ss.data[0] == '/' && isalpha( (unsigned char) ss.data[1]) && ss.data[2] == ':' ) { +#else + if (ss.data[ 0 ] == '/' && isalpha( ss.data[ 1 ] ) && ss.data[ 2 ] == ':') { +#endif + --ss.length; ::memmove( ss.data, ss.data+1, ss.length); ss.data[ss.length] = 0; } From f7d0e05018cbb94afca918e72150825bae678982 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 10 May 2018 14:21:43 +0200 Subject: [PATCH 201/278] closes https://github.com/assimp/assimp/issues/1952: check for postprocessing parameter before try to parse -f --- tools/assimp_cmd/Export.cpp | 3 +- tools/assimp_cmd/Main.cpp | 75 +++++++++++++++++-------------------- 2 files changed, 37 insertions(+), 41 deletions(-) diff --git a/tools/assimp_cmd/Export.cpp b/tools/assimp_cmd/Export.cpp index 55c017e33..03f896822 100644 --- a/tools/assimp_cmd/Export.cpp +++ b/tools/assimp_cmd/Export.cpp @@ -106,7 +106,8 @@ int Assimp_Export(const char* const* params, unsigned int num) continue; } if (!strncmp( params[i], "-f",2)) { - outf = std::string(params[i]+2); + if ( strncmp( params[ i ], "-fi",3 )) + outf = std::string(params[i]+2); } else if ( !strncmp( params[i], "--format=",9)) { outf = std::string(params[i]+9); diff --git a/tools/assimp_cmd/Main.cpp b/tools/assimp_cmd/Main.cpp index 14d00e1e1..41412b93d 100644 --- a/tools/assimp_cmd/Main.cpp +++ b/tools/assimp_cmd/Main.cpp @@ -261,7 +261,6 @@ void PrintHorBar() printf("-----------------------------------------------------------------\n"); } - // ------------------------------------------------------------------------------ // Import a specific file const aiScene* ImportModel( @@ -390,105 +389,101 @@ int ProcessStandardArguments( for (unsigned int i = 0; i < num;++i) { - if (! strcmp(params[i], "-ptv") || ! strcmp(params[i], "--pretransform-vertices")) { + const char *param = params[ i ]; + printf( "param = %s\n", param ); + if (! strcmp( param, "-ptv") || ! strcmp( param, "--pretransform-vertices")) { fill.ppFlags |= aiProcess_PreTransformVertices; } - else if (! strcmp(params[i], "-gsn") || ! strcmp(params[i], "--gen-smooth-normals")) { + else if (! strcmp( param, "-gsn") || ! strcmp( param, "--gen-smooth-normals")) { fill.ppFlags |= aiProcess_GenSmoothNormals; } - else if (! strcmp(params[i], "-gn") || ! strcmp(params[i], "--gen-normals")) { + else if (! strcmp( param, "-gn") || ! strcmp( param, "--gen-normals")) { fill.ppFlags |= aiProcess_GenNormals; } - else if (! strcmp(params[i], "-jiv") || ! strcmp(params[i], "--join-identical-vertices")) { + else if (! strcmp( param, "-jiv") || ! strcmp( param, "--join-identical-vertices")) { fill.ppFlags |= aiProcess_JoinIdenticalVertices; } - else if (! strcmp(params[i], "-rrm") || ! strcmp(params[i], "--remove-redundant-materials")) { + else if (! strcmp( param, "-rrm") || ! strcmp( param, "--remove-redundant-materials")) { fill.ppFlags |= aiProcess_RemoveRedundantMaterials; } - else if (! strcmp(params[i], "-fd") || ! strcmp(params[i], "--find-degenerates")) { + else if (! strcmp( param, "-fd") || ! strcmp( param, "--find-degenerates")) { fill.ppFlags |= aiProcess_FindDegenerates; } - else if (! strcmp(params[i], "-slm") || ! strcmp(params[i], "--split-large-meshes")) { + else if (! strcmp( param, "-slm") || ! strcmp( param, "--split-large-meshes")) { fill.ppFlags |= aiProcess_SplitLargeMeshes; } - else if (! strcmp(params[i], "-lbw") || ! strcmp(params[i], "--limit-bone-weights")) { + else if (! strcmp( param, "-lbw") || ! strcmp( param, "--limit-bone-weights")) { fill.ppFlags |= aiProcess_LimitBoneWeights; } - else if (! strcmp(params[i], "-vds") || ! strcmp(params[i], "--validate-data-structure")) { + else if (! strcmp( param, "-vds") || ! strcmp( param, "--validate-data-structure")) { fill.ppFlags |= aiProcess_ValidateDataStructure; } - else if (! strcmp(params[i], "-icl") || ! strcmp(params[i], "--improve-cache-locality")) { + else if (! strcmp( param, "-icl") || ! strcmp( param, "--improve-cache-locality")) { fill.ppFlags |= aiProcess_ImproveCacheLocality; } - else if (! strcmp(params[i], "-sbpt") || ! strcmp(params[i], "--sort-by-ptype")) { + else if (! strcmp( param, "-sbpt") || ! strcmp( param, "--sort-by-ptype")) { fill.ppFlags |= aiProcess_SortByPType; } - else if (! strcmp(params[i], "-lh") || ! strcmp(params[i], "--left-handed")) { + else if (! strcmp( param, "-lh") || ! strcmp( param, "--left-handed")) { fill.ppFlags |= aiProcess_ConvertToLeftHanded; } - else if (! strcmp(params[i], "-fuv") || ! strcmp(params[i], "--flip-uv")) { + else if (! strcmp( param, "-fuv") || ! strcmp( param, "--flip-uv")) { fill.ppFlags |= aiProcess_FlipUVs; } - else if (! strcmp(params[i], "-fwo") || ! strcmp(params[i], "--flip-winding-order")) { + else if (! strcmp( param, "-fwo") || ! strcmp( param, "--flip-winding-order")) { fill.ppFlags |= aiProcess_FlipWindingOrder; } - else if (! strcmp(params[i], "-tuv") || ! strcmp(params[i], "--transform-uv-coords")) { + else if (! strcmp( param, "-tuv") || ! strcmp( param, "--transform-uv-coords")) { fill.ppFlags |= aiProcess_TransformUVCoords; } - else if (! strcmp(params[i], "-guv") || ! strcmp(params[i], "--gen-uvcoords")) { + else if (! strcmp( param, "-guv") || ! strcmp( param, "--gen-uvcoords")) { fill.ppFlags |= aiProcess_GenUVCoords; } - else if (! strcmp(params[i], "-fid") || ! strcmp(params[i], "--find-invalid-data")) { + else if (! strcmp( param, "-fid") || ! strcmp( param, "--find-invalid-data")) { fill.ppFlags |= aiProcess_FindInvalidData; } - else if (! strcmp(params[i], "-fixn") || ! strcmp(params[i], "--fix-normals")) { + else if (! strcmp( param, "-fixn") || ! strcmp( param, "--fix-normals")) { fill.ppFlags |= aiProcess_FixInfacingNormals; } - else if (! strcmp(params[i], "-tri") || ! strcmp(params[i], "--triangulate")) { + else if (! strcmp( param, "-tri") || ! strcmp( param, "--triangulate")) { fill.ppFlags |= aiProcess_Triangulate; } - else if (! strcmp(params[i], "-cts") || ! strcmp(params[i], "--calc-tangent-space")) { + else if (! strcmp( param, "-cts") || ! strcmp( param, "--calc-tangent-space")) { fill.ppFlags |= aiProcess_CalcTangentSpace; } - else if (! strcmp(params[i], "-fi") || ! strcmp(params[i], "--find-instances")) { + else if (! strcmp( param, "-fi") || ! strcmp( param, "--find-instances")) { fill.ppFlags |= aiProcess_FindInstances; } - else if (! strcmp(params[i], "-og") || ! strcmp(params[i], "--optimize-graph")) { + else if (! strcmp( param, "-og") || ! strcmp( param, "--optimize-graph")) { fill.ppFlags |= aiProcess_OptimizeGraph; } - else if (! strcmp(params[i], "-om") || ! strcmp(params[i], "--optimize-meshes")) { + else if (! strcmp( param, "-om") || ! strcmp( param, "--optimize-meshes")) { fill.ppFlags |= aiProcess_OptimizeMeshes; } - else if (! strcmp(params[i], "-db") || ! strcmp(params[i], "--debone")) { + else if (! strcmp( param, "-db") || ! strcmp( param, "--debone")) { fill.ppFlags |= aiProcess_Debone; } - else if (! strcmp(params[i], "-sbc") || ! strcmp(params[i], "--split-by-bone-count")) { + else if (! strcmp( param, "-sbc") || ! strcmp( param, "--split-by-bone-count")) { fill.ppFlags |= aiProcess_SplitByBoneCount; } - - - else if (! strncmp(params[i], "-c",2) || ! strncmp(params[i], "--config=",9)) { - + else if (! strncmp( param, "-c",2) || ! strncmp( param, "--config=",9)) { const unsigned int ofs = (params[i][1] == '-' ? 9 : 2); // use default configurations - if (! strncmp(params[i]+ofs,"full",4)) { - fill.ppFlags |= aiProcessPreset_TargetRealtime_MaxQuality; - } - else if (! strncmp(params[i]+ofs,"default",7)) { + if (!strncmp( param + ofs, "full", 4 )) { + fill.ppFlags |= aiProcessPreset_TargetRealtime_MaxQuality; + } else if (!strncmp( param + ofs, "default", 7 )) { fill.ppFlags |= aiProcessPreset_TargetRealtime_Quality; - } - else if (! strncmp(params[i]+ofs,"fast",4)) { + } else if (! strncmp( param +ofs,"fast",4)) { fill.ppFlags |= aiProcessPreset_TargetRealtime_Fast; } - } - else if (! strcmp(params[i], "-l") || ! strcmp(params[i], "--show-log")) { + } else if (! strcmp( param, "-l") || ! strcmp( param, "--show-log")) { fill.showLog = true; } - else if (! strcmp(params[i], "-v") || ! strcmp(params[i], "--verbose")) { + else if (! strcmp( param, "-v") || ! strcmp( param, "--verbose")) { fill.verbose = true; } - else if (! strncmp(params[i], "--log-out=",10) || ! strncmp(params[i], "-lo",3)) { + else if (! strncmp( param, "--log-out=",10) || ! strncmp( param, "-lo",3)) { fill.logFile = std::string(params[i]+(params[i][1] == '-' ? 10 : 3)); if (!fill.logFile.length()) { fill.logFile = "assimp-log.txt"; From 1c9406b2f59d5235f2b69192551f4cae391f4c92 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 12 May 2018 08:09:07 +0200 Subject: [PATCH 202/278] add linetest files to gitignore. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2a3b68a50..f8dda3e8b 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,7 @@ tools/assimp_cmd/Makefile # Tests test/results +test/readlinetest* # Python __pycache__ From ef605fecaa4c51f3b59f5d1038a9f7ddd2417967 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 12 May 2018 08:09:27 +0200 Subject: [PATCH 203/278] FBX: small optimization to avoind static computation in loop. --- code/FBXBinaryTokenizer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/FBXBinaryTokenizer.cpp b/code/FBXBinaryTokenizer.cpp index d6c34de6f..b81a9f945 100644 --- a/code/FBXBinaryTokenizer.cpp +++ b/code/FBXBinaryTokenizer.cpp @@ -448,8 +448,8 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int le /*Result ignored*/ ReadByte(input, cursor, input + length); const uint32_t version = ReadWord(input, cursor, input + length); const bool is64bits = version >= 7500; - while (cursor < input + length) - { + const char *end = input + length; + while (cursor < end ) { if (!ReadScope(output_tokens, input, cursor, input + length, is64bits)) { break; } From f93ee9daced8e77227bdeba50fffd5e596eabe99 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 12 May 2018 08:10:26 +0200 Subject: [PATCH 204/278] closes https://github.com/assimp/assimp/issues/1780: check against nullptr before accessing normal data in aiMesh instance. --- code/glTF2Exporter.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index 5376788b2..9bb99b0b0 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -728,8 +728,10 @@ void glTF2Exporter::ExportMeshes() /******************** Normals ********************/ // Normalize all normals as the validator can emit a warning otherwise - for (auto i = 0u; i < aim->mNumVertices; ++i) { - aim->mNormals[i].Normalize(); + if ( nullptr != aim->mNormals) { + for ( auto i = 0u; i < aim->mNumVertices; ++i ) { + aim->mNormals[ i ].Normalize(); + } } Ref n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); From 950496c351ff7a438c812b6b4719343d8ea4ccd9 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 12 May 2018 08:39:22 +0200 Subject: [PATCH 205/278] some minor refactorings. --- code/glTF2Exporter.cpp | 17 ++++++++++------- code/glTF2Exporter.h | 28 ++++++++++++---------------- test/unit/utglTF2ImportExport.cpp | 1 + 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index 9bb99b0b0..d4b3d67de 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -138,28 +138,29 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai } } +glTF2Exporter::~glTF2Exporter() { + // empty +} + /* * Copy a 4x4 matrix from struct aiMatrix to typedef mat4. * Also converts from row-major to column-major storage. */ -static void CopyValue(const aiMatrix4x4& v, mat4& o) -{ +static void CopyValue(const aiMatrix4x4& v, mat4& o) { o[ 0] = v.a1; o[ 1] = v.b1; o[ 2] = v.c1; o[ 3] = v.d1; o[ 4] = v.a2; o[ 5] = v.b2; o[ 6] = v.c2; o[ 7] = v.d2; o[ 8] = v.a3; o[ 9] = v.b3; o[10] = v.c3; o[11] = v.d3; o[12] = v.a4; o[13] = v.b4; o[14] = v.c4; o[15] = v.d4; } -static void CopyValue(const aiMatrix4x4& v, aiMatrix4x4& o) -{ +static void CopyValue(const aiMatrix4x4& v, aiMatrix4x4& o) { o.a1 = v.a1; o.a2 = v.a2; o.a3 = v.a3; o.a4 = v.a4; o.b1 = v.b1; o.b2 = v.b2; o.b3 = v.b3; o.b4 = v.b4; o.c1 = v.c1; o.c2 = v.c2; o.c3 = v.c3; o.c4 = v.c4; o.d1 = v.d1; o.d2 = v.d2; o.d3 = v.d3; o.d4 = v.d4; } -static void IdentityMatrix4(mat4& o) -{ +static void IdentityMatrix4(mat4& o) { o[ 0] = 1; o[ 1] = 0; o[ 2] = 0; o[ 3] = 0; o[ 4] = 0; o[ 5] = 1; o[ 6] = 0; o[ 7] = 0; o[ 8] = 0; o[ 9] = 0; o[10] = 1; o[11] = 0; @@ -169,7 +170,9 @@ static void IdentityMatrix4(mat4& o) inline Ref ExportData(Asset& a, std::string& meshName, Ref& buffer, unsigned int count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, bool isIndices = false) { - if (!count || !data) return Ref(); + if (!count || !data) { + return Ref(); + } unsigned int numCompsIn = AttribType::GetNumComponents(typeIn); unsigned int numCompsOut = AttribType::GetNumComponents(typeOut); diff --git a/code/glTF2Exporter.h b/code/glTF2Exporter.h index ff94be9e9..616a1177c 100644 --- a/code/glTF2Exporter.h +++ b/code/glTF2Exporter.h @@ -87,28 +87,15 @@ namespace Assimp // ------------------------------------------------------------------------------------------------ /** Helper class to export a given scene to an glTF file. */ // ------------------------------------------------------------------------------------------------ - class glTF2Exporter - { + class glTF2Exporter { public: /// Constructor for a specific scene to export glTF2Exporter(const char* filename, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties, bool binary); + ~glTF2Exporter(); - private: - - const char* mFilename; - IOSystem* mIOSystem; - const aiScene* mScene; - const ExportProperties* mProperties; - - std::map mTexturesByPath; - - std::shared_ptr mAsset; - - std::vector mBodyData; - + protected: void WriteBinaryData(IOStream* outfile, std::size_t sceneLength); - void GetTexSampler(const aiMaterial* mat, glTF2::Ref texture, aiTextureType tt, unsigned int slot); void GetMatTexProp(const aiMaterial* mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int idx); void GetMatTexProp(const aiMaterial* mat, float& prop, const char* propName, aiTextureType tt, unsigned int idx); @@ -126,6 +113,15 @@ namespace Assimp unsigned int ExportNode(const aiNode* node, glTF2::Ref& parent); void ExportScene(); void ExportAnimations(); + + private: + const char* mFilename; + IOSystem* mIOSystem; + const aiScene* mScene; + const ExportProperties* mProperties + std::map mTexturesByPath; + std::shared_ptr mAsset; + std::vector mBodyData; }; } diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp index 91b8917a8..58ebe3017 100644 --- a/test/unit/utglTF2ImportExport.cpp +++ b/test/unit/utglTF2ImportExport.cpp @@ -89,4 +89,5 @@ TEST_F( utglTF2ImportExport, importBinaryglTF2FromFileTest ) { TEST_F( utglTF2ImportExport, exportglTF2FromFileTest ) { EXPECT_TRUE( exporterTest() ); } + #endif // ASSIMP_BUILD_NO_EXPORT From e3548fe85046eda679a064bee81db815a8e45e16 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 12 May 2018 08:50:17 +0200 Subject: [PATCH 206/278] Update glTF2Exporter.h Fix typo. --- code/glTF2Exporter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/glTF2Exporter.h b/code/glTF2Exporter.h index 616a1177c..06bc5ad40 100644 --- a/code/glTF2Exporter.h +++ b/code/glTF2Exporter.h @@ -118,7 +118,7 @@ namespace Assimp const char* mFilename; IOSystem* mIOSystem; const aiScene* mScene; - const ExportProperties* mProperties + const ExportProperties* mProperties; std::map mTexturesByPath; std::shared_ptr mAsset; std::vector mBodyData; From a571d013102b62b437b4623dd4fc28a042dc5945 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 12 May 2018 12:01:52 +0200 Subject: [PATCH 207/278] Create CONTRIBUTING.md --- CONTRIBUTING.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..6aebbbd01 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,11 @@ +#How to contribute + +If you want to contribute you can follow these setps: +- Fist create your own clone of assimp +- When you want to fix a bug or add a new feature create a branch on your own fork ( just follow https://help.github.com/articles/creating-a-pull-request-from-a-fork/ ) +- Push it to the repo and open a pull request +- A pull request will start our CI-service, which checks if the build works for linux and windows. + It will check for memory leaks, compiler warnings and memory alignment issues. If any of these tests fails: fix it and the tests will be reastarted automatically + - At the end we will perform a code review and merge your branch to the master branch. + + From 2998830d4a555f8aeccec8843152f0e3c217ca00 Mon Sep 17 00:00:00 2001 From: Alexandre Avenel Date: Sun, 13 May 2018 15:33:51 +0200 Subject: [PATCH 208/278] Fix typos on documentation using codespell --- Readme.md | 2 +- doc/dox.h | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Readme.md b/Readme.md index c78a0c1c8..856371d7e 100644 --- a/Readme.md +++ b/Readme.md @@ -141,7 +141,7 @@ Open Asset Import Library is implemented in C++. The directory structure is: /samples A small number of samples to illustrate possible use cases for Assimp /workspaces Build environments for vc,xcode,... (deprecated, - CMake has superseeded all legacy build options!) + CMake has superseded all legacy build options!) ### Where to get help ### diff --git a/doc/dox.h b/doc/dox.h index bc47e5584..af9eeb609 100644 --- a/doc/dox.h +++ b/doc/dox.h @@ -164,7 +164,7 @@ If done correctly you should now be able to compile, link, run and use the appli @section install_own Building the library from scratch First you need to install cmake. Now just get the code from github or download the latest version from the webside. -to buil the library just open a command-prompt / bash, navigate into the repo-folder and run cmake via: +to build the library just open a command-prompt / bash, navigate into the repo-folder and run cmake via: @code cmake CMakeLists.txt @@ -653,7 +653,7 @@ To apply such an animation you need to identify the animation tracks that refer in your mesh. Then for every track:
a) Find the keys that lay right before the current anim time.
b) Optional: interpolate between these and the following keys.
-c) Combine the calculated position, rotation and scaling to a tranformation matrix
+c) Combine the calculated position, rotation and scaling to a transformation matrix
d) Set the affected node's transformation to the calculated matrix.
If you need hints on how to convert to or from quaternions, have a look at the @@ -669,7 +669,7 @@ Such textures are loaded into an aiTexture structure. In previous versions, the path from the query for `AI_MATKEY_TEXTURE(textureType, index)` would be `*` where `` is the index of the texture in aiScene::mTextures. Now this call will -return a file path for embedded textures in FBX files. To test if it is an embdedded texture use +return a file path for embedded textures in FBX files. To test if it is an embedded texture use aiScene::GetEmbeddedTexture. If the returned pointer is not null, it is embedded und can be loaded from the data structure. If it is null, search for a separate file. Other file types still use the old behaviour.
@@ -794,7 +794,7 @@ All material key constants start with 'AI_MATKEY' (it's an ugly macro for histor COLOR_REFLECTIVE aiColor3D black (0,0,0) - Defines the reflective color of the material. This is typically scaled by the amount of incoming light from the direction of mirror reflection. Usually combined with an enviroment lightmap of some kind for real-time applications. + Defines the reflective color of the material. This is typically scaled by the amount of incoming light from the direction of mirror reflection. Usually combined with an environment lightmap of some kind for real-time applications. --- @@ -819,7 +819,7 @@ All material key constants start with 'AI_MATKEY' (it's an ugly macro for histor int false Specifies whether meshes using this material must be rendered without backface culling. 0 for false, !0 for true. - Some importers set this property if they don't know whether the output face oder is right. As long as it is not set, you may safely enable backface culling. + Some importers set this property if they don't know whether the output face order is right. As long as it is not set, you may safely enable backface culling. From 2879e0d6ef21a34180da13dd9f0a66b16d54b095 Mon Sep 17 00:00:00 2001 From: Alexandre Avenel Date: Sun, 13 May 2018 16:35:03 +0200 Subject: [PATCH 209/278] Fix typos on code using codespell --- code/AMFImporter_Macro.hpp | 8 ++++---- code/AMFImporter_Material.cpp | 2 +- code/AMFImporter_Postprocess.cpp | 2 +- code/ASEParser.h | 2 +- code/BlenderDNA.cpp | 2 +- code/BlenderDNA.h | 2 +- code/BlenderTessellator.h | 2 +- code/ColladaExporter.h | 2 +- code/ColladaLoader.cpp | 4 ++-- code/FBXConverter.cpp | 2 +- code/FBXDocument.cpp | 6 +++--- code/FBXExporter.cpp | 22 +++++++++++----------- code/FBXExporter.h | 2 +- code/FBXMaterial.cpp | 2 +- code/FindDegenerates.cpp | 2 +- code/IRRShared.h | 2 +- code/Importer.cpp | 18 +++++++++--------- code/Importer/IFC/IFCUtil.cpp | 2 +- code/JoinVerticesProcess.cpp | 2 +- code/LWSLoader.cpp | 2 +- code/MDLLoader.cpp | 4 ++-- code/MMDImporter.cpp | 2 +- code/NFFLoader.cpp | 4 ++-- code/OpenGEXImporter.cpp | 2 +- code/OptimizeGraph.h | 2 +- code/ProcessHelper.h | 2 +- code/ScenePreprocessor.cpp | 2 +- code/StandardShapes.cpp | 2 +- code/StepExporter.cpp | 2 +- code/TextureTransform.cpp | 2 +- code/Version.cpp | 2 +- code/X3DExporter.hpp | 2 +- code/X3DImporter.hpp | 2 +- code/X3DImporter_Geometry3D.cpp | 8 ++++---- code/X3DImporter_Macro.hpp | 4 ++-- code/X3DImporter_Metadata.cpp | 2 +- code/XFileExporter.cpp | 2 +- code/XGLLoader.cpp | 2 +- code/glTF2Asset.h | 2 +- code/glTFAsset.h | 2 +- code/glTFExporter.cpp | 2 +- 41 files changed, 71 insertions(+), 71 deletions(-) diff --git a/code/AMFImporter_Macro.hpp b/code/AMFImporter_Macro.hpp index afa120028..ea8c17850 100644 --- a/code/AMFImporter_Macro.hpp +++ b/code/AMFImporter_Macro.hpp @@ -71,7 +71,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. } /// \def MACRO_ATTRREAD_CHECK_REF -/// Check curent attribute name and if it equal to requested then read value. Result write to output variable by reference. If result was read then +/// Check current attribute name and if it equal to requested then read value. Result write to output variable by reference. If result was read then /// "continue" will called. /// \param [in] pAttrName - attribute name. /// \param [out] pVarName - output variable name. @@ -84,7 +84,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. } /// \def MACRO_ATTRREAD_CHECK_RET -/// Check curent attribute name and if it equal to requested then read value. Result write to output variable using return value of \ref pFunction. +/// Check current attribute name and if it equal to requested then read value. Result write to output variable using return value of \ref pFunction. /// If result was read then "continue" will called. /// \param [in] pAttrName - attribute name. /// \param [out] pVarName - output variable name. @@ -130,7 +130,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. } while(false) /// \def MACRO_NODECHECK_READCOMP_F -/// Check curent node name and if it equal to requested then read value. Result write to output variable of type "float". +/// Check current node name and if it equal to requested then read value. Result write to output variable of type "float". /// If result was read then "continue" will called. Also check if node data already read then raise exception. /// \param [in] pNodeName - node name. /// \param [in, out] pReadFlag - read flag. @@ -147,7 +147,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. } /// \def MACRO_NODECHECK_READCOMP_U32 -/// Check curent node name and if it equal to requested then read value. Result write to output variable of type "uint32_t". +/// Check current node name and if it equal to requested then read value. Result write to output variable of type "uint32_t". /// If result was read then "continue" will called. Also check if node data already read then raise exception. /// \param [in] pNodeName - node name. /// \param [in, out] pReadFlag - read flag. diff --git a/code/AMFImporter_Material.cpp b/code/AMFImporter_Material.cpp index 77f49d39e..2f65ad833 100644 --- a/code/AMFImporter_Material.cpp +++ b/code/AMFImporter_Material.cpp @@ -99,7 +99,7 @@ CAMFImporter_NodeElement* ne; ParseHelper_Node_Exit(); // check that all components was defined if(!(read_flag[0] && read_flag[1] && read_flag[2])) throw DeadlyImportError("Not all color components are defined."); - // check if is absent. Then manualy add "a == 1". + // check if is absent. Then manually add "a == 1". if(!read_flag[3]) als.Color.a = 1; }// if(!mReader->isEmptyElement()) diff --git a/code/AMFImporter_Postprocess.cpp b/code/AMFImporter_Postprocess.cpp index 192544fcb..a6ee8fa2f 100644 --- a/code/AMFImporter_Postprocess.cpp +++ b/code/AMFImporter_Postprocess.cpp @@ -770,7 +770,7 @@ std::list ch_node; // find referenced object if(!Find_ConvertedNode(als.ObjectID, pNodeList, &found_node)) Throw_ID_NotFound(als.ObjectID); - // create node for apllying transformation + // create node for applying transformation t_node = new aiNode; t_node->mParent = con_node; // apply transformation diff --git a/code/ASEParser.h b/code/ASEParser.h index 8715fdfab..70eb3de66 100644 --- a/code/ASEParser.h +++ b/code/ASEParser.h @@ -427,7 +427,7 @@ public: // ------------------------------------------------------------------- //! Construct a parser from a given input file which is - //! guaranted to be terminated with zero. + //! guaranteed to be terminated with zero. //! @param szFile Input file //! @param fileFormatDefault Assumed file format version. If the //! file format is specified in the file the new value replaces diff --git a/code/BlenderDNA.cpp b/code/BlenderDNA.cpp index afcbb34e3..f84c45601 100644 --- a/code/BlenderDNA.cpp +++ b/code/BlenderDNA.cpp @@ -227,7 +227,7 @@ void DNAParser::Parse () // ------------------------------------------------------------------------------------------------ void DNA :: DumpToFile() { - // we dont't bother using the VFS here for this is only for debugging. + // we don't bother using the VFS here for this is only for debugging. // (and all your bases are belong to us). std::ofstream f("dna.txt"); diff --git a/code/BlenderDNA.h b/code/BlenderDNA.h index 4a1e83b64..6a18fe9fa 100644 --- a/code/BlenderDNA.h +++ b/code/BlenderDNA.h @@ -663,7 +663,7 @@ public: /** Check whether a specific item is in the cache. * @param s Data type of the item * @param out Output pointer. Unchanged if the - * cache doens't know the item yet. + * cache doesn't know the item yet. * @param ptr Item address to look for. */ template void get ( const Structure& s, diff --git a/code/BlenderTessellator.h b/code/BlenderTessellator.h index 59d698295..dab3ba8aa 100644 --- a/code/BlenderTessellator.h +++ b/code/BlenderTessellator.h @@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INCLUDED_AI_BLEND_TESSELLATOR_H // Use these to toggle between GLU Tessellate or poly2tri -// Note (acg) keep GLU Tesselate disabled by default - if it is turned on, +// Note (acg) keep GLU Tessellate disabled by default - if it is turned on, // assimp needs to be linked against GLU, which is currently not yet // made configurable in CMake and potentially not wanted by most users // as it requires a Gl environment. diff --git a/code/ColladaExporter.h b/code/ColladaExporter.h index 773039735..d1a307532 100644 --- a/code/ColladaExporter.h +++ b/code/ColladaExporter.h @@ -189,7 +189,7 @@ protected: {} }; - // summarize a material in an convinient way. + // summarize a material in an convenient way. struct Material { std::string name; diff --git a/code/ColladaLoader.cpp b/code/ColladaLoader.cpp index 611e487b0..54178295c 100644 --- a/code/ColladaLoader.cpp +++ b/code/ColladaLoader.cpp @@ -956,7 +956,7 @@ void ColladaLoader::StoreSceneMaterials( aiScene* pScene) // Stores all animations void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pParser) { - // recursivly collect all animations from the collada scene + // recursively collect all animations from the collada scene StoreAnimations( pScene, pParser, &pParser.mAnims, ""); // catch special case: many animations with the same length, each affecting only a single node. @@ -1784,7 +1784,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars // TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING" // In FBX files textures are now stored internally by Assimp with their filename included - // Now Assimp can lookup thru the loaded textures after all data is processed + // Now Assimp can lookup through the loaded textures after all data is processed // We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it // This may occur on this case too, it has to be studied // setup texture reference string diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index d6529d119..c50e88390 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -1564,7 +1564,7 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap& if (textureReady) { // TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING" // In FBX files textures are now stored internally by Assimp with their filename included - // Now Assimp can lookup thru the loaded textures after all data is processed + // Now Assimp can lookup through the loaded textures after all data is processed // We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it // This may occur on this case too, it has to be studied path.data[0] = '*'; diff --git a/code/FBXDocument.cpp b/code/FBXDocument.cpp index 2965a54ff..f53ae4405 100644 --- a/code/FBXDocument.cpp +++ b/code/FBXDocument.cpp @@ -575,11 +575,11 @@ std::vector Document::GetConnectionsSequenced(uint64_t id, bo ai_assert( count != 0 ); ai_assert( count <= MAX_CLASSNAMES); - size_t lenghts[MAX_CLASSNAMES]; + size_t lengths[MAX_CLASSNAMES]; const size_t c = count; for (size_t i = 0; i < c; ++i) { - lenghts[ i ] = strlen(classnames[i]); + lengths[ i ] = strlen(classnames[i]); } std::vector temp; @@ -597,7 +597,7 @@ std::vector Document::GetConnectionsSequenced(uint64_t id, bo for (size_t i = 0; i < c; ++i) { ai_assert(classnames[i]); - if(static_cast(std::distance(key.begin(),key.end())) == lenghts[i] && !strncmp(classnames[i],obtype,lenghts[i])) { + if(static_cast(std::distance(key.begin(),key.end())) == lengths[i] && !strncmp(classnames[i],obtype,lengths[i])) { obtype = NULL; break; } diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index 52c69161a..a942e31bc 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -450,7 +450,7 @@ void FBXExporter::WriteDocuments () p.AddP70string("ActiveAnimStackName", ""); // should do this properly? doc.AddChild(p); - // UID for root node in scene heirarchy. + // UID for root node in scene hierarchy. // always set to 0 in the case of a single document. // not sure what happens if more than one document exists, // but that won't matter to us as we're exporting a single scene. @@ -650,7 +650,7 @@ void FBXExporter::WriteDefinitions () } // Model / FbxNode - // <~~ node heirarchy + // <~~ node hierarchy count = int32_t(count_nodes(mScene->mRootNode)) - 1; // (not counting root node) if (count) { n = FBX::Node("ObjectType", "Model"); @@ -1223,7 +1223,7 @@ void FBXExporter::WriteObjects () // it's all about this material aiMaterial* m = mScene->mMaterials[i]; - // these are used to recieve material data + // these are used to receive material data float f; aiColor3D c; // start the node record @@ -1311,7 +1311,7 @@ void FBXExporter::WriteObjects () // Now the legacy system. // For safety let's include it. // thrse values don't exist in the property template, - // and usualy are completely ignored when loading. + // and usually are completely ignored when loading. // One notable exception is the "Opacity" property, // which Blender uses as (1.0 - alpha). c.r = 0.0f; c.g = 0.0f; c.b = 0.0f; @@ -1532,7 +1532,7 @@ void FBXExporter::WriteObjects () // bones. // // output structure: - // subset of node heirarchy that are "skeleton", + // subset of node hierarchy that are "skeleton", // i.e. do not have meshes but only bones. // but.. i'm not sure how anyone could guarantee that... // @@ -1544,7 +1544,7 @@ void FBXExporter::WriteObjects () // // well. we can assume a sane input, i suppose. // - // so input is the bone node heirarchy, + // so input is the bone node hierarchy, // with an extra thing for the transformation of the MESH in BONE space. // // output is a set of bone nodes, @@ -1556,7 +1556,7 @@ void FBXExporter::WriteObjects () // and represents the influence of that bone on the grandparent mesh. // the subdeformer has a list of indices, and weights, // with indices specifying vertex indices, - // and weights specifying the correspoding influence of this bone. + // and weights specifying the corresponding influence of this bone. // it also has Transform and TransformLink elements, // specifying the transform of the MESH in BONE space, // and the transformation of the BONE in WORLD space, @@ -1806,7 +1806,7 @@ void FBXExporter::WriteObjects () // and a correct skeleton would still be output. // transformlink should be the position of the bone in world space. - // if the bone is in the bind pose (or nonexistant), + // if the bone is in the bind pose (or nonexistent), // we can just use the matrix we already calculated if (bone_xform_okay) { sdnode.AddChild("TransformLink", bone_xform); @@ -1945,7 +1945,7 @@ void FBXExporter::WriteObjects () // TODO: cameras, lights - // write nodes (i.e. model heirarchy) + // write nodes (i.e. model hierarchy) // start at root node WriteModelNodes( outstream, mScene->mRootNode, 0, limbnodes @@ -2203,8 +2203,8 @@ void FBXExporter::WriteModelNode( } else { // apply the transformation chain. // these transformation elements are created when importing FBX, - // which has a complex transformation heirarchy for each node. - // as such we can bake the heirarchy back into the node on export. + // which has a complex transformation hierarchy for each node. + // as such we can bake the hierarchy back into the node on export. for (auto &item : transform_chain) { auto elem = transform_types.find(item.first); if (elem == transform_types.end()) { diff --git a/code/FBXExporter.h b/code/FBXExporter.h index 3b9de8acb..c27d1a8ce 100644 --- a/code/FBXExporter.h +++ b/code/FBXExporter.h @@ -90,7 +90,7 @@ namespace Assimp const ExportProperties* mProperties; // currently unused std::shared_ptr outfile; // file to write to - std::vector connections; // conection storage + std::vector connections; // connection storage std::vector mesh_uids; std::vector material_uids; diff --git a/code/FBXMaterial.cpp b/code/FBXMaterial.cpp index 8bb3920de..75b2e3b4b 100644 --- a/code/FBXMaterial.cpp +++ b/code/FBXMaterial.cpp @@ -302,7 +302,7 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std } if(Content) { - //this field is ommited when the embedded texture is already loaded, let's ignore if it's not found + //this field is omitted when the embedded texture is already loaded, let's ignore if it's not found try { const Token& token = GetRequiredToken(*Content, 0); const char* data = token.begin(); diff --git a/code/FindDegenerates.cpp b/code/FindDegenerates.cpp index c0023c9a4..760ab743a 100644 --- a/code/FindDegenerates.cpp +++ b/code/FindDegenerates.cpp @@ -161,7 +161,7 @@ void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) { // NOTE: we set the removed vertex index to an unique value // to make sure the developer gets notified when his - // application attemps to access this data. + // application attempts to access this data. face.mIndices[ face.mNumIndices ] = 0xdeadbeef; if(first) { diff --git a/code/IRRShared.h b/code/IRRShared.h index 8770d2add..2f6f87405 100644 --- a/code/IRRShared.h +++ b/code/IRRShared.h @@ -91,7 +91,7 @@ protected: // ------------------------------------------------------------------- /** Read a property of the specified type from the current XML element. - * @param out Recives output data + * @param out Receives output data */ void ReadHexProperty (HexProperty& out); void ReadStringProperty (StringProperty& out); diff --git a/code/Importer.cpp b/code/Importer.cpp index 9fbba61c4..139dc6c51 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -997,33 +997,33 @@ bool Importer::SetPropertyInteger(const char* szName, int iValue) // Set a configuration property bool Importer::SetPropertyFloat(const char* szName, ai_real iValue) { - bool exising; + bool existing; ASSIMP_BEGIN_EXCEPTION_REGION(); - exising = SetGenericProperty(pimpl->mFloatProperties, szName,iValue); + existing = SetGenericProperty(pimpl->mFloatProperties, szName,iValue); ASSIMP_END_EXCEPTION_REGION(bool); - return exising; + return existing; } // ------------------------------------------------------------------------------------------------ // Set a configuration property bool Importer::SetPropertyString(const char* szName, const std::string& value) { - bool exising; + bool existing; ASSIMP_BEGIN_EXCEPTION_REGION(); - exising = SetGenericProperty(pimpl->mStringProperties, szName,value); + existing = SetGenericProperty(pimpl->mStringProperties, szName,value); ASSIMP_END_EXCEPTION_REGION(bool); - return exising; + return existing; } // ------------------------------------------------------------------------------------------------ // Set a configuration property bool Importer::SetPropertyMatrix(const char* szName, const aiMatrix4x4& value) { - bool exising; + bool existing; ASSIMP_BEGIN_EXCEPTION_REGION(); - exising = SetGenericProperty(pimpl->mMatrixProperties, szName,value); + existing = SetGenericProperty(pimpl->mMatrixProperties, szName,value); ASSIMP_END_EXCEPTION_REGION(bool); - return exising; + return existing; } // ------------------------------------------------------------------------------------------------ diff --git a/code/Importer/IFC/IFCUtil.cpp b/code/Importer/IFC/IFCUtil.cpp index 97f621935..06cc4405a 100644 --- a/code/Importer/IFC/IFCUtil.cpp +++ b/code/Importer/IFC/IFCUtil.cpp @@ -317,7 +317,7 @@ void TempMesh::FixupFaceOrientation() IfcVector3 farthestCenter = std::accumulate(mVerts.begin() + faceStartIndices[farthestIndex], mVerts.begin() + faceStartIndices[farthestIndex] + mVertcnt[farthestIndex], IfcVector3(0.0)) / IfcFloat(mVertcnt[farthestIndex]); - // We accapt a bit of negative orientation without reversing. In case of doubt, prefer the orientation given in + // We accept a bit of negative orientation without reversing. In case of doubt, prefer the orientation given in // the file. if( (farthestNormal * (farthestCenter - vavg).Normalize()) < -0.4 ) { diff --git a/code/JoinVerticesProcess.cpp b/code/JoinVerticesProcess.cpp index c21d71f47..7f7bcae41 100644 --- a/code/JoinVerticesProcess.cpp +++ b/code/JoinVerticesProcess.cpp @@ -118,7 +118,7 @@ bool areVerticesEqual(const Vertex &lhs, const Vertex &rhs, bool complex) // Squared because we check against squared length of the vector difference static const float squareEpsilon = epsilon * epsilon; - // Square compare is useful for animeshes vertexes compare + // Square compare is useful for animeshes vertices compare if ((lhs.position - rhs.position).SquareLength() > squareEpsilon) { return false; } diff --git a/code/LWSLoader.cpp b/code/LWSLoader.cpp index 518b893e9..6f8cbe78d 100644 --- a/code/LWSLoader.cpp +++ b/code/LWSLoader.cpp @@ -410,7 +410,7 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector unique due to LWs indexing system lit->mName = nd->mName; - // detemine light type and setup additional members + // determine light type and setup additional members if (src.lightType == 2) { /* spot light */ lit->mType = aiLightSource_SPOT; diff --git a/code/MDLLoader.cpp b/code/MDLLoader.cpp index 4c43bc64f..dfe1c1311 100644 --- a/code/MDLLoader.cpp +++ b/code/MDLLoader.cpp @@ -141,7 +141,7 @@ void MDLImporter::SetupProperties(const Importer* pImp) configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0); } - // AI_CONFIG_IMPORT_MDL_COLORMAP - pallette file + // AI_CONFIG_IMPORT_MDL_COLORMAP - palette file configPalette = pImp->GetPropertyString(AI_CONFIG_IMPORT_MDL_COLORMAP,"colormap.lmp"); } @@ -1496,7 +1496,7 @@ void MDLImporter::InternReadFile_3DGS_MDL7( ) groupData.vTextureCoords1.resize(iNumVertices,aiVector3D()); // check whether the triangle data structure is large enough - // to contain a second UV coodinate set + // to contain a second UV coordinate set if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV) { groupData.vTextureCoords2.resize(iNumVertices,aiVector3D()); groupData.bNeed2UV = true; diff --git a/code/MMDImporter.cpp b/code/MMDImporter.cpp index 76ad9115c..3d7f3c794 100644 --- a/code/MMDImporter.cpp +++ b/code/MMDImporter.cpp @@ -217,7 +217,7 @@ aiMesh *MMDImporter::CreateMesh(const pmx::PmxModel *pModel, pMesh->mNumFaces = indexCount / 3; pMesh->mFaces = new aiFace[pMesh->mNumFaces]; - const int numIndices = 3; // trianglular face + const int numIndices = 3; // triangular face for (unsigned int index = 0; index < pMesh->mNumFaces; index++) { pMesh->mFaces[index].mNumIndices = numIndices; unsigned int *indices = new unsigned int[numIndices]; diff --git a/code/NFFLoader.cpp b/code/NFFLoader.cpp index 2c7eeaa20..1c7283db6 100644 --- a/code/NFFLoader.cpp +++ b/code/NFFLoader.cpp @@ -271,7 +271,7 @@ void NFFImporter::InternReadFile( const std::string& pFile, ShadingInfo s; // current material info - // degree of tesselation + // degree of tessellation unsigned int iTesselation = 4; // some temporary variables we need to parse the file @@ -988,7 +988,7 @@ void NFFImporter::InternReadFile( const std::string& pFile, ::ai_snprintf(currentMesh.name,128,"cone_%i",cone++); else ::ai_snprintf(currentMesh.name,128,"cylinder_%i",cylinder++); } - // 'tess' - tesselation + // 'tess' - tessellation else if (TokenMatch(sz,"tess",4)) { SkipSpaces(&sz); diff --git a/code/OpenGEXImporter.cpp b/code/OpenGEXImporter.cpp index 9966c1f34..2de0aabc0 100644 --- a/code/OpenGEXImporter.cpp +++ b/code/OpenGEXImporter.cpp @@ -691,7 +691,7 @@ void OpenGEXImporter::handleTransformNode( ODDLParser::DDLNode *node, aiScene * void OpenGEXImporter::handleMeshNode( ODDLParser::DDLNode *node, aiScene *pScene ) { m_currentMesh = new aiMesh; const size_t meshidx( m_meshCache.size() ); - // ownership is transfered but a reference remains in m_currentMesh + // ownership is transferred but a reference remains in m_currentMesh m_meshCache.emplace_back( m_currentMesh ); Property *prop = node->getProperties(); diff --git a/code/OptimizeGraph.h b/code/OptimizeGraph.h index aa6aa8651..6781ec534 100644 --- a/code/OptimizeGraph.h +++ b/code/OptimizeGraph.h @@ -102,7 +102,7 @@ public: } // ------------------------------------------------------------------- - /** @brief Rmeove a node from the list of locked nodes. + /** @brief Remove a node from the list of locked nodes. * @param name Name to be unlocked */ inline void RemoveLockedNode(std::string& name) diff --git a/code/ProcessHelper.h b/code/ProcessHelper.h index c668b946f..dcf71e853 100644 --- a/code/ProcessHelper.h +++ b/code/ProcessHelper.h @@ -212,7 +212,7 @@ template <> struct MinMaxChooser { // ------------------------------------------------------------------------------- /** @brief Find the min/max values of an array of Ts * @param in Input array - * @param size Numebr of elements to process + * @param size Number of elements to process * @param[out] min minimum value * @param[out] max maximum value */ diff --git a/code/ScenePreprocessor.cpp b/code/ScenePreprocessor.cpp index eff6ecc6e..1228ab2c2 100644 --- a/code/ScenePreprocessor.cpp +++ b/code/ScenePreprocessor.cpp @@ -104,7 +104,7 @@ void ScenePreprocessor::ProcessMesh (aiMesh* mesh) aiVector3D* p = mesh->mTextureCoords[i], *end = p+mesh->mNumVertices; - // Ensure unsued components are zeroed. This will make 1D texture channels work + // Ensure unused components are zeroed. This will make 1D texture channels work // as if they were 2D channels .. just in case an application doesn't handle // this case if (2 == mesh->mNumUVComponents[i]) { diff --git a/code/StandardShapes.cpp b/code/StandardShapes.cpp index a5b368f7f..7d2319401 100644 --- a/code/StandardShapes.cpp +++ b/code/StandardShapes.cpp @@ -377,7 +377,7 @@ void StandardShapes::MakeSphere(unsigned int tess, MakeIcosahedron(positions); // ... and subdivide it until the requested output - // tesselation is reached + // tessellation is reached for (unsigned int i = 0; i& pVertices); diff --git a/code/X3DImporter_Geometry3D.cpp b/code/X3DImporter_Geometry3D.cpp index a366e8062..b6d130098 100644 --- a/code/X3DImporter_Geometry3D.cpp +++ b/code/X3DImporter_Geometry3D.cpp @@ -136,7 +136,7 @@ void X3DImporter::ParseNode_Geometry3D_Cone() } else { - const unsigned int tess = 30;///TODO: IME tesselation factor through ai_property + const unsigned int tess = 30;///TODO: IME tessellation factor through ai_property std::vector tvec;// temp array for vertices. @@ -209,7 +209,7 @@ void X3DImporter::ParseNode_Geometry3D_Cylinder() } else { - const unsigned int tess = 30;///TODO: IME tesselation factor through ai_property + const unsigned int tess = 30;///TODO: IME tessellation factor through ai_property std::vector tside;// temp array for vertices of side. std::vector tcir;// temp array for vertices of circle. @@ -480,7 +480,7 @@ static aiVector3D GeometryHelper_Extrusion_GetNextY(const size_t pSpine_PointIdx tvec = pSpine[1] - pSpine[0]; } else - {// The Y-axis used for the last point it is the vector from spine[n-2] to spine[n-1]. In our case(see above about droping tail) spine[n - 1] is + {// The Y-axis used for the last point it is the vector from spine[n-2] to spine[n-1]. In our case(see above about dropping tail) spine[n - 1] is // the spine[0]. tvec = pSpine[spine_idx_last] - pSpine[spine_idx_last - 1]; } @@ -967,7 +967,7 @@ void X3DImporter::ParseNode_Geometry3D_Sphere() } else { - const unsigned int tess = 3;///TODO: IME tesselation factor through ai_property + const unsigned int tess = 3;///TODO: IME tessellation factor through ai_property std::vector tlist; diff --git a/code/X3DImporter_Macro.hpp b/code/X3DImporter_Macro.hpp index cff521408..d1172798c 100644 --- a/code/X3DImporter_Macro.hpp +++ b/code/X3DImporter_Macro.hpp @@ -76,7 +76,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. } /// \def MACRO_ATTRREAD_CHECK_REF -/// Check curent attribute name and if it equal to requested then read value. Result write to output variable by reference. If result was read then +/// Check current attribute name and if it equal to requested then read value. Result write to output variable by reference. If result was read then /// "continue" will called. /// \param [in] pAttrName - attribute name. /// \param [out] pVarName - output variable name. @@ -89,7 +89,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. } /// \def MACRO_ATTRREAD_CHECK_RET -/// Check curent attribute name and if it equal to requested then read value. Result write to output variable using return value of \ref pFunction. +/// Check current attribute name and if it equal to requested then read value. Result write to output variable using return value of \ref pFunction. /// If result was read then "continue" will called. /// \param [in] pAttrName - attribute name. /// \param [out] pVarName - output variable name. diff --git a/code/X3DImporter_Metadata.cpp b/code/X3DImporter_Metadata.cpp index 0dc9bcec1..a566f0aa9 100644 --- a/code/X3DImporter_Metadata.cpp +++ b/code/X3DImporter_Metadata.cpp @@ -79,7 +79,7 @@ namespace Assimp if(!mReader->isEmptyElement()) \ ParseNode_Metadata(pNE, pMetaName);/* in that case node element will be added to child elements list of current node. */ \ else \ - NodeElement_Cur->Child.push_back(pNE);/* else - add element to child list manualy */ \ + NodeElement_Cur->Child.push_back(pNE);/* else - add element to child list manually */ \ \ NodeElement_List.push_back(pNE);/* add new element to elements list. */ \ }/* if(!pUSE_Var.empty()) else */ \ diff --git a/code/XFileExporter.cpp b/code/XFileExporter.cpp index b2862c6d9..1510ae6d4 100644 --- a/code/XFileExporter.cpp +++ b/code/XFileExporter.cpp @@ -132,7 +132,7 @@ void XFileExporter::WriteFile() { // note, that all realnumber values must be comma separated in x files mOutput.setf(std::ios::fixed); - mOutput.precision(16); // precission for double + mOutput.precision(16); // precision for double // entry of writing the file WriteHeader(); diff --git a/code/XGLLoader.cpp b/code/XGLLoader.cpp index a9fd6a5ab..0706ffd55 100644 --- a/code/XGLLoader.cpp +++ b/code/XGLLoader.cpp @@ -498,7 +498,7 @@ aiMatrix4x4 XGLImporter::ReadTrafo() right = forward ^ up; if (std::fabs(up * forward) > 1e-4) { // this is definitely wrong - a degenerate coordinate space ruins everything - // so subtitute identity transform. + // so substitute identity transform. LogError(" and vectors in are skewing, ignoring trafo"); return m; } diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 358d6bcb4..dd9b11df5 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -386,7 +386,7 @@ namespace glTF2 }; - //! Base classe for all glTF top-level objects + //! Base class for all glTF top-level objects struct Object { int index; //!< The index of this object within its property container diff --git a/code/glTFAsset.h b/code/glTFAsset.h index 018106309..bc79f72ec 100644 --- a/code/glTFAsset.h +++ b/code/glTFAsset.h @@ -381,7 +381,7 @@ namespace glTF }; - //! Base classe for all glTF top-level objects + //! Base class for all glTF top-level objects struct Object { std::string id; //!< The globally unique ID used to reference this object diff --git a/code/glTFExporter.cpp b/code/glTFExporter.cpp index 7dfe5b3ff..29a88af8b 100644 --- a/code/glTFExporter.cpp +++ b/code/glTFExporter.cpp @@ -703,7 +703,7 @@ void glTFExporter::ExportMeshes() // Coordinates indices comp_o3dgc_ifs.SetNCoordIndex(aim->mNumFaces); comp_o3dgc_ifs.SetCoordIndex((IndicesType* const)&b->GetPointer()[idx_srcdata_ind]); - // Prepare to enconding + // Prepare to encoding comp_o3dgc_params.SetNumFloatAttributes(comp_o3dgc_ifs.GetNumFloatAttributes()); if(mProperties->GetPropertyBool("extensions.Open3DGC.binary", true)) comp_o3dgc_params.SetStreamType(o3dgc::O3DGC_STREAM_TYPE_BINARY); From d8af63519d7feef64a5a01aa71f78cab143cfed3 Mon Sep 17 00:00:00 2001 From: Lieven Dekeyser Date: Tue, 15 May 2018 12:38:50 +0200 Subject: [PATCH 210/278] Create fat binaries for libIrrXML and libzlibstatic too --- port/iOS/build.sh | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/port/iOS/build.sh b/port/iOS/build.sh index 44683f0c7..cf17240ab 100755 --- a/port/iOS/build.sh +++ b/port/iOS/build.sh @@ -59,9 +59,9 @@ build_arch() $XCODE_ROOT_DIR/Developer/usr/bin/make clean $XCODE_ROOT_DIR/Developer/usr/bin/make assimp -j 8 -l - echo "[!] Moving built library into: $BUILD_DIR/$1/" + echo "[!] Moving built libraries into: $BUILD_DIR/$1/" - mv ./lib/libassimp.a $BUILD_DIR/$1/ + mv ./lib/*.a $BUILD_DIR/$1/ } echo "[!] $0 - assimp iOS build script" @@ -110,14 +110,27 @@ for ARCH_TARGET in $DEPLOY_ARCHS; do #rm ./lib/libassimp.a done -if [[ "$DEPLOY_FAT" -eq 1 ]]; then - echo '[+] Creating fat binary ...' + +make_fat_binary() +{ + LIB_NAME=$1 + LIPO_ARGS='' for ARCH_TARGET in $DEPLOY_ARCHS; do - LIPO_ARGS="$LIPO_ARGS-arch $ARCH_TARGET $BUILD_DIR/$ARCH_TARGET/libassimp.a " + LIPO_ARGS="$LIPO_ARGS-arch $ARCH_TARGET $BUILD_DIR/$ARCH_TARGET/$LIB_NAME.a " done - LIPO_ARGS="$LIPO_ARGS-create -output $BUILD_DIR/libassimp-fat.a" + LIPO_ARGS="$LIPO_ARGS-create -output $BUILD_DIR/$LIB_NAME-fat.a" lipo $LIPO_ARGS - echo "[!] Done! The fat binary can be found at $BUILD_DIR" +} + +if [[ "$DEPLOY_FAT" -eq 1 ]]; then + echo '[+] Creating fat binaries ...' + + make_fat_binary 'libassimp' + make_fat_binary 'libIrrXML' + make_fat_binary 'libzlibstatic' + + echo "[!] Done! The fat binaries can be found at $BUILD_DIR" fi + From f4fd5840b143b5e57cbb820e9804386d414b6bf3 Mon Sep 17 00:00:00 2001 From: Andor Goetzendorff Date: Tue, 15 May 2018 15:22:19 +0200 Subject: [PATCH 211/278] Encode filename using file system encoding instead of ASCII --- port/PyAssimp/pyassimp/core.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/port/PyAssimp/pyassimp/core.py b/port/PyAssimp/pyassimp/core.py index 573ce27b1..8950e54aa 100644 --- a/port/PyAssimp/pyassimp/core.py +++ b/port/PyAssimp/pyassimp/core.py @@ -312,7 +312,7 @@ def load(filename, file_type) else: # a filename string has been passed - model = _assimp_lib.load(filename.encode("ascii"), processing) + model = _assimp_lib.load(filename.encode(sys.getfilesystemencoding()), processing) if not model: raise AssimpError('Could not import file!') @@ -342,7 +342,7 @@ def export(scene, ''' from ctypes import pointer - exportStatus = _assimp_lib.export(pointer(scene), file_type.encode("ascii"), filename.encode("ascii"), processing) + exportStatus = _assimp_lib.export(pointer(scene), file_type.encode("ascii"), filename.encode(sys.getfilesystemencoding()), processing) if exportStatus != 0: raise AssimpError('Could not export scene!') From 46ed73c768461e3e853ecd35d1d4200d32e69763 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20L=C3=B6ber?= Date: Wed, 16 May 2018 11:02:07 +0200 Subject: [PATCH 212/278] Do not throw exception on empty mesh after removal of degenerates Remove mesh instead. This keeps one edge case open: nodes without mesh references. They are kept as it is for now (they may stilol contain transformations and child references). --- code/FindDegenerates.cpp | 56 +++++++++++++++++++++++++++++++++++++--- code/FindDegenerates.h | 3 ++- 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/code/FindDegenerates.cpp b/code/FindDegenerates.cpp index c0023c9a4..7bc6186bb 100644 --- a/code/FindDegenerates.cpp +++ b/code/FindDegenerates.cpp @@ -54,6 +54,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; +//remove mesh at position 'index' from the scene +static void removeMesh(aiScene* pScene, unsigned const index); +//correct node indices to meshes and remove references to deleted mesh +static void updateSceneGraph(aiNode* pNode, unsigned const index); + // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer FindDegeneratesProcess::FindDegeneratesProcess() @@ -87,11 +92,50 @@ void FindDegeneratesProcess::SetupProperties(const Importer* pImp) { void FindDegeneratesProcess::Execute( aiScene* pScene) { ASSIMP_LOG_DEBUG("FindDegeneratesProcess begin"); for (unsigned int i = 0; i < pScene->mNumMeshes;++i){ - ExecuteOnMesh( pScene->mMeshes[ i ] ); + if (ExecuteOnMesh(pScene->mMeshes[i])) { + removeMesh(pScene, i); + --i; //the current i is removed, do not skip the next one + } } ASSIMP_LOG_DEBUG("FindDegeneratesProcess finished"); } +static void removeMesh(aiScene* pScene, unsigned const index) { + //we start at index and copy the pointers one position forward + //save the mesh pointer to delete it later + auto delete_me = pScene->mMeshes[index]; + for (unsigned i = index; i < pScene->mNumMeshes - 1; ++i) { + pScene->mMeshes[i] = pScene->mMeshes[i+1]; + } + pScene->mMeshes[pScene->mNumMeshes - 1] = nullptr; + --(pScene->mNumMeshes); + delete delete_me; + + //removing a mesh also requires updating all references to it in the scene graph + updateSceneGraph(pScene->mRootNode, index); +} + +static void updateSceneGraph(aiNode* pNode, unsigned const index) { + for (unsigned i = 0; i < pNode->mNumMeshes; ++i) { + if (pNode->mMeshes[i] > index) { + --(pNode->mMeshes[i]); + continue; + } + if (pNode->mMeshes[i] == index) { + for (unsigned j = i; j < pNode->mNumMeshes -1; ++j) { + pNode->mMeshes[j] = pNode->mMeshes[j+1]; + } + --(pNode->mNumMeshes); + --i; + continue; + } + } + //recurse to all children + for (unsigned i = 0; i < pNode->mNumChildren; ++i) { + updateSceneGraph(pNode->mChildren[i], index); + } +} + static ai_real heron( ai_real a, ai_real b, ai_real c ) { ai_real s = (a + b + c) / 2; ai_real area = pow((s * ( s - a ) * ( s - b ) * ( s - c ) ), (ai_real)0.5 ); @@ -125,7 +169,7 @@ static ai_real calculateAreaOfTriangle( const aiFace& face, aiMesh* mesh ) { // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported mesh -void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) { +bool FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) { mesh->mPrimitiveTypes = 0; std::vector remove_me; @@ -227,19 +271,22 @@ evil_jump_outside: if (&face_src != &face_dest) { // clear source face_src.mNumIndices = 0; - face_src.mIndices = NULL; + face_src.mIndices = nullptr; } } else { // Otherwise delete it if we don't need this face delete[] face_src.mIndices; - face_src.mIndices = NULL; + face_src.mIndices = nullptr; face_src.mNumIndices = 0; } } // Just leave the rest of the array unreferenced, we don't care for now mesh->mNumFaces = n; if (!mesh->mNumFaces) { + //The whole mesh consists of degenerated faces + //signal upward, that this mesh should be deleted. + return true; // WTF!? // OK ... for completeness and because I'm not yet tired, // let's write code that will hopefully never be called @@ -253,4 +300,5 @@ evil_jump_outside: if (deg && !DefaultLogger::isNullLogger()) { ASSIMP_LOG_WARN_F( "Found ", deg, " degenerated primitives"); } + return false; } diff --git a/code/FindDegenerates.h b/code/FindDegenerates.h index 2df94710a..c234c57f5 100644 --- a/code/FindDegenerates.h +++ b/code/FindDegenerates.h @@ -74,7 +74,8 @@ public: // ------------------------------------------------------------------- // Execute step on a given mesh - void ExecuteOnMesh( aiMesh* mesh); + ///@returns true if the current mesh should be deleted, false otherwise + bool ExecuteOnMesh( aiMesh* mesh); // ------------------------------------------------------------------- /// @brief Enable the instant removal of degenerated primitives From 9e80e18b1a331a9b284cd9cbd0f7caeb8d612314 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20L=C3=B6ber?= Date: Wed, 16 May 2018 11:10:48 +0200 Subject: [PATCH 213/278] Remove dead code --- code/FindDegenerates.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/code/FindDegenerates.cpp b/code/FindDegenerates.cpp index 7bc6186bb..3917975fd 100644 --- a/code/FindDegenerates.cpp +++ b/code/FindDegenerates.cpp @@ -286,14 +286,8 @@ evil_jump_outside: if (!mesh->mNumFaces) { //The whole mesh consists of degenerated faces //signal upward, that this mesh should be deleted. + ASSIMP_LOG_DEBUG("FindDegeneratesProcess removed a mesh full of degenerated primitives"); return true; - // WTF!? - // OK ... for completeness and because I'm not yet tired, - // let's write code that will hopefully never be called - // (famous last words) - - // OK ... bad idea. - throw DeadlyImportError("Mesh is empty after removal of degenerated primitives ... WTF!?"); } } From 7251c3c51a774c2828f62787e3aa6ad743ca5628 Mon Sep 17 00:00:00 2001 From: Andreas Sturmlechner Date: Wed, 16 May 2018 13:45:25 +0200 Subject: [PATCH 214/278] Fix build with Qt 5.11.0_beta3 (qt5_use_modules is gone) --- tools/assimp_qt_viewer/CMakeLists.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/assimp_qt_viewer/CMakeLists.txt b/tools/assimp_qt_viewer/CMakeLists.txt index 42ef0fb34..9f1b68cab 100644 --- a/tools/assimp_qt_viewer/CMakeLists.txt +++ b/tools/assimp_qt_viewer/CMakeLists.txt @@ -3,7 +3,7 @@ project(assimp_qt_viewer) cmake_minimum_required(VERSION 2.6) -find_package(Qt5Widgets REQUIRED) +find_package(Qt5 COMPONENTS Gui Widgets OpenGL REQUIRED) find_package(DevIL REQUIRED) find_package(OpenGL REQUIRED) @@ -25,9 +25,8 @@ qt5_wrap_ui(UISrcs mainwindow.ui) qt5_wrap_cpp(MOCrcs mainwindow.hpp glview.hpp) add_executable(${PROJECT_NAME} ${assimp_qt_viewer_SRCS} ${UISrcs} ${MOCrcs}) -target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES} ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTOPENGL_LIBRARY} ${IL_LIBRARIES} ${OPENGL_LIBRARIES} assimp) +target_link_libraries(${PROJECT_NAME} Qt5::Gui Qt5::Widgets Qt5::OpenGL ${IL_LIBRARIES} ${OPENGL_LIBRARIES} assimp) -qt5_use_modules(${PROJECT_NAME} Widgets OpenGL) if(WIN32) # Check if we are on Windows if(MSVC) # Check if we are using the Visual Studio compiler #set_target_properties(TestProject PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS") From 5bbf0a8afa5a3cbaa9281e47cc327b0d9560b03f Mon Sep 17 00:00:00 2001 From: Andreas Sturmlechner Date: Wed, 16 May 2018 13:58:30 +0200 Subject: [PATCH 215/278] Add missing assimp_qt_viewer install target --- tools/assimp_qt_viewer/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/assimp_qt_viewer/CMakeLists.txt b/tools/assimp_qt_viewer/CMakeLists.txt index 9f1b68cab..b41291e3d 100644 --- a/tools/assimp_qt_viewer/CMakeLists.txt +++ b/tools/assimp_qt_viewer/CMakeLists.txt @@ -42,3 +42,5 @@ else() endif() set_property(TARGET ${PROJECT_NAME} PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) + +install(TARGETS assimp_qt_viewer DESTINATION "${ASSIMP_BIN_INSTALL_DIR}") From df9faaae41d65e41209ae011beca38e973d5bf2d Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 16 May 2018 19:39:27 +0200 Subject: [PATCH 216/278] Update Readme.md Remove deprecated doc. --- Readme.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/Readme.md b/Readme.md index 856371d7e..449efc547 100644 --- a/Readme.md +++ b/Readme.md @@ -140,8 +140,6 @@ Open Asset Import Library is implemented in C++. The directory structure is: /tools Tools (old assimp viewer, command line `assimp`) /samples A small number of samples to illustrate possible use cases for Assimp - /workspaces Build environments for vc,xcode,... (deprecated, - CMake has superseded all legacy build options!) ### Where to get help ### From 224b43a3a9c8993c0ca96b1189ba91d968fe4e5d Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 16 May 2018 21:19:30 +0200 Subject: [PATCH 217/278] Update CHANGES Add 4.1.0 release notes --- CHANGES | 258 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 258 insertions(+) diff --git a/CHANGES b/CHANGES index d5faab2e0..c0c73b98c 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,264 @@ ---------------------------------------------------------------------- CHANGELOG ---------------------------------------------------------------------- +4.1.0 (2017-12): +- FEATURES: + - Export 3MF ( experimental ) + - Import / Export glTF 2 + - Introduce new zib-lib to eb able to export zip-archives +- FIXES/HOUSEKEEPING: + - Added missing include to stdlib.h and remove load library call + - Fix install for builds with MSVC compiler and NMake. + - Update list of supported file formats. + - Add TriLib to the official list of supported ports. + - Re-enabling PACK_STRUCT for MDL files. + - Use std.::unique_ptr + - Update D3MFExporter.h + - Update MD3Loader.cpp, using index + - Fix all warnings on MSVC14 + - Copy assimp dll to unit folder on windows + - Update jvm port supported formats + - Add support for building Mac OS X Framework bundles + - Check for nullptr dereferencing before copying scene data + - Update ValidateDataStructure.h, typo + - Enable data structure validation in cases where it doesn't cause failures + - Remove some dead assignments + - fast_atof: Silence some uninitialized variable warnings + - Check for area test if the face is a triangle. + - Set mNumUVComponents to 0 when deleting texture coordinate sets + - Only scale the root node because this will rescale all children nodes as well. + - Issue 1514: Fix frame pointer arithmetic + - Prevent failing stringstream to crash the export process + - powf -> pow + - add Defines.h to include folder for install. + - Android: + - Fix android build + - Fix assimp for cross compile for android + - Use define for D_FILE_OFFSET_BITS only for not-android systems. + - FBX: + - Fix handling with embedded textures + - FBX 7500 Binary reading + - Remove dead assignment + - Fix export of deleted meshes; Add LazyDict::Remove method + - Log an error instead of letting the fbx-importer crash. ( issue 213 ) + - Replace bad pointer casting with memcpy + - Remove useless const qualifier from return value + - Add explicit instantiation of log_prefix so other FBX source files can see it + - add missing inversion of postrotation matrix for fbx. + - FIReader: Silence uninitialized variable warning + - Update version check in FBX reader to check for version >= 7500 + - Use actual min/max of anim keys when start/stop time is missing +- GLTF1: + - Fix output of glTF 1 version string + - Fix delete / delete[] mismatch in glTFAsset + - Don’t ignore rgba(1,1,1,1) color properties + - glTF2 primitives fixes + - Don’t ignore rgba(1,1,1,1) color properties + - Fix delete / delete[] mismatch in glTFAsset + - Remove KHR_binary_glTF code + - glTF nodes can only hold one mesh. this simply assigns to and check’s a Node’s Mesh + - version in glb header is stored as uint32_t +- GLTF2: + - node name conflict fix + - Fix transform matrices multiplication order + - Preserve node names when importing + - Add support for tangents in import + - Fix typo on gltf2 camera parameters + - Moved byteStride from accessor to bufferView + - Implemented reading binary glTF2 (glb) files + - Fix signed/unsigned warning + - Add postprocess step for scaling + - Fix shininess to roughness conversion + - Prefer “BLEND” over “MASK” as an alphaMode default + - Approximate specularity / glossiness in metallicRoughness materials + - Diffuse color and diffuse texture import and export improvements + - Addressed some mismatched news/deletes caused by the new glTF2 sources. + - Fix delete / delete[] mismatches in glTF2 importer + - use correct name of exporter to gltf2 + - Fix possible infinite loop when exporting to gltf2 + - Fix glTF2::Asset::FindUniqueID() when the input string is >= 256 chars + - Fix glTF2 alphaMode storage and reading + - Fix glTF 2.0 multi-primitive support + - Load gltf .bin files from correct directory + - Add support for importing both glTF and glTF2 files + - ampler improvements; Add new LazyDict method + - Changes to GLTF2 materials + - Remove Light, Technique references + - Start removing materials common, and adding pbrSpecularGlossiness + - Use !ObjectEmpty() vs. MemberCount() > 0 + - Working read, import, export, and write of gltf2 (pbr) material + - Check in gltf2 models to test directory + - Remove un-needed test models + - Start managing and importing gltf2 pbr materials + - Update glTF2 Asset to use indexes + - Duplicate gltfImporter as gltf2Importer; Include glTF2 importer in CMake List + - glTF2: Fix animation export + - use opacity for diffuse alpha + alphaMode +- STL: + - Restore import of multi mesh binary STLs +- Blender: + - Silence warning about uninitialized member +- MDLImporter: + - Don't take address of packed struct member +- assimp_cmd: + - Fix strict-aliasing warnings +- Open3DGC: + - Fix strict-aliasing warnings + - Add assertions to silence static analyzer warnings + - Remove redundant const qualifiers from return types + - Fix some uninitialized variable warnings + - Remove OPEN3DGC and compression references +- unzip: + - Remove dead assignment + - Bail on bad compression method + - Fix possibly uninitialized variables +- clipper: + - Add assertion to silence a static analyzer warning +- OpenDDLExport: + - Reduce scope of a variable + - Remove dead variable + - Remove dead assignment + - Fix another potential memory leak +- X3DImporter: + - Add assertions to silence static analyzer warnings + - Add missing unittest + - Workaround for buggy Android NDK (issue #1361) +- TerragenLoader: + - Remove unused variable +- SIBImporter: + - Add assertions to silence static analyzer warnings +- IFC: + - Remove dead code + - Add explicit instantiation of log_prefix so IFCMaterial.cpp can see it +- PLY: + - Remove dead assignment and reduce scope of a variable + - fix vertex attribute lookup. +- OpenGEX: + - Add assertion to silence a static analyzer warning + - Fix for TextureFile with number in file name + - Return early when element is TextureFile +- NFF: + - Add assertions to silence static analyzer warnings + - Split up some complicated assignments +- Raw: Fix misleading indentation warning + - Reduce scope of a variable +- LWO + - Reduce scope of a variable +- IRRLoader: + - Fix confusing boolean casting +- AssbinExporter: + - Add assertion to silence a static analyzer warning +- ASE: + - Add assertion to silence a static analyzer warning +- AMFImporter: + - Add assertion to silence a static analyzer warning + - Add a block +- OptimizeGraph: + - Fix possible null pointer dereference + - RemoveRedundantMaterials: + - Add assertion to silence a static analyzer warning +- ImproveCacheLocality: + - Add assertion to silence a static analyzer warning +- RemoveRedundantMaterials: + - Set pointer to nullptr after deleting it +- Travis: + - Disable unit tests in scan-build config + - Move slower builds earlier to improve parallelization + - Add static analysis to build + - Remove unused branch rule for travis. + - Add Clang UBSan build configuration + - Treat warnings as errors, without typos this time +- Unittests: + - Add VS-based source groups for the unittests. +- Collada: + - export tag + - Update ColladaExporter.cpp + - Silence uninitialized variable warning + - Add support for line strip primitives +- Obj Wavefront: + - check in exporting against out-of-bounds-access . + - Issue 1351: use correct name for obj-meshname export for groups. + - fix mem-lead: face will be not released in case of an error. + - Anatoscope obj exporter nomtl + - Raise exception when obj file contains invalid face indices + - Added alternative displacement texture token in OBJ MTL material. + - Obj: rename attribute from exporter. + - Fix OBJ discarding all material names if the material library is missing +- Step: + - use correct lookup for utf32 +- MD2: + - Fix MD2 frames containing garbage +- STL + - add missing const. + - Fix memory-alignment bug. + - Fix issue 104: deal with more solids in one STL file. +- CMake + - Fix issue 213: use correct include folder for assimp +- Doxygen + - Fix issue 1513: put irrXML onto exclucde list for doxygen run +- PyAssimp: + - Search for libassimp.so in LD_LIBRARY_PATH if available. + - Fix operator precedence issue in header check + - Split setup.py into multiple lines + - Detect if Anaconda and fixed 3d_viewer for Python 3 + - created a python3 version of the 3dviewer and fixed the / = float in py3 +- Blender: + - Fix invalid access to mesh array when the array is empty. + - Fix short overflow. + - Silence warning about inline function which is declared but not defined +- JAssimp + - Changed license header for IHMC contributions from Apache 2.0 to BSD + - Add Node metadata to the Jassmip Java API + - Added supported for custom IO Systems in Java. Implemented ClassLoader IO System + - Added a link to pure jvm assimp port +- Clang sanitizer: + - Undefined Behavior sanitizer + - Fixed a divide by zero error in IFCBoolean that was latent, but nevertheless a bug +- B3DImporter: + - Replace bad pointer casting with memcpy +- AppVeyor: + - Cleanup and Addition of VS 2017 and running Tests + - Fixed File Size reported as 0 in tests that use temporary files + - x86 isn't a valid VS platform. Win32 it is, then. + - Replaced the worker image name, which doesn't work as generator name, with a manually created generator name. + - Cleaned up appveyor setup, added VS 2017 to the build matrix and attempted to add running of tests. + - Treat warnings as errors on Appveyor + - Disable warning 4351 on MSVC 2013 +- OpenGEXImporter: + - Copy materials to scene + - Store RefInfo in unique_ptr so they get automatically cleaned up + - Fix IOStream leak + - Store ChildInfo in unique_ptr so they get automatically cleaned up + - improve logging to be able to detect error-prone situations. +- AMFImporter: + - Fix memory leak +- UnrealLoader: + - Fix IOStream leak +- Upgrade RapidJSON to get rid of a clang warning +- zlib: + - Update zlib contribution + - Removed unnecessary files from zlib contribution + - Replaced unsigned long for the crc table to z_crc_t, to match what is returned by get-crc_table +- MakeVerboseFormat: + - Fix delete / delete[] mismatches in MakeVerboseFormat +- MaterialSystem: + - Fix out-of-bounds read in MaterialSystem unit test +- SIB: + - Added support for SIB models from Silo 2.5 +- AssbinExporter: + - Fix strict aliasing violation + - Add Write specialization for aiColor3D +- DefaultLogger: + - Whitespace cleanup to fix GCC misleading indentation warning +- MDP: + - Fix encoding issues. + - PreTransformVertices: + - fix name lost in mesh and nodes when load with flag +- C4D: + - Fixes for C4D importer +- Unzip: + - Latest greatest. + 4.0.1 (2017-07-28) - FIXES/HOUSEKEEPING: - fix version test. From a1a17c1dda127adbd571fb063af9309eebaac4bd Mon Sep 17 00:00:00 2001 From: Stanlo Slasinski Date: Fri, 18 May 2018 14:01:25 -0700 Subject: [PATCH 218/278] Read and write the KHR_materials_unlit glTF/2.0 extension. --- code/glTF2Asset.h | 5 +++++ code/glTF2Asset.inl | 4 ++++ code/glTF2AssetWriter.h | 1 + code/glTF2AssetWriter.inl | 10 ++++++++++ code/glTF2Exporter.cpp | 6 ++++++ code/glTF2Importer.cpp | 3 +++ include/assimp/pbrmaterial.h | 1 + 7 files changed, 30 insertions(+) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index dd9b11df5..0ce843d09 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * glTF Extensions Support: * KHR_materials_pbrSpecularGlossiness full + * KHR_materials_unlit full */ #ifndef GLTF2ASSET_H_INC #define GLTF2ASSET_H_INC @@ -741,6 +742,9 @@ namespace glTF2 //extension: KHR_materials_pbrSpecularGlossiness Nullable pbrSpecularGlossiness; + //extension: KHR_materials_unlit + bool unlit; + Material() { SetDefaults(); } void Read(Value& obj, Asset& r); void SetDefaults(); @@ -1037,6 +1041,7 @@ namespace glTF2 struct Extensions { bool KHR_materials_pbrSpecularGlossiness; + bool KHR_materials_unlit; } extensionsUsed; diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index d96db6d74..acf8cb331 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -860,6 +860,8 @@ inline void Material::Read(Value& material, Asset& r) this->pbrSpecularGlossiness = Nullable(pbrSG); } } + + unlit = nullptr != FindObject(*extensions, "KHR_materials_unlit"); } } @@ -882,6 +884,7 @@ inline void Material::SetDefaults() alphaMode = "OPAQUE"; alphaCutoff = 0.5; doubleSided = false; + unlit = false; } inline void PbrSpecularGlossiness::SetDefaults() @@ -1253,6 +1256,7 @@ inline void Asset::ReadExtensionsUsed(Document& doc) if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true; CHECK_EXT(KHR_materials_pbrSpecularGlossiness); + CHECK_EXT(KHR_materials_unlit); #undef CHECK_EXT } diff --git a/code/glTF2AssetWriter.h b/code/glTF2AssetWriter.h index e2b97e8c4..493ca1c0a 100644 --- a/code/glTF2AssetWriter.h +++ b/code/glTF2AssetWriter.h @@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * glTF Extensions Support: * KHR_materials_pbrSpecularGlossiness: full + * KHR_materials_unlit: full */ #ifndef GLTF2ASSETWRITER_H_INC #define GLTF2ASSETWRITER_H_INC diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index 6be012676..0579dfdac 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -343,6 +343,12 @@ namespace glTF2 { } } + if (m.unlit) { + Value unlit; + unlit.SetObject(); + exts.AddMember("KHR_materials_unlit", unlit, w.mAl); + } + if (!exts.ObjectEmpty()) { obj.AddMember("extensions", exts, w.mAl); } @@ -683,6 +689,10 @@ namespace glTF2 { if (this->mAsset.extensionsUsed.KHR_materials_pbrSpecularGlossiness) { exts.PushBack(StringRef("KHR_materials_pbrSpecularGlossiness"), mAl); } + + if (this->mAsset.extensionsUsed.KHR_materials_unlit) { + exts.PushBack(StringRef("KHR_materials_unlit"), mAl); + } } if (!exts.Empty()) diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index d4b3d67de..9e8dfc822 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -526,6 +526,12 @@ void glTF2Exporter::ExportMaterials() m->pbrSpecularGlossiness = Nullable(pbrSG); } + + bool unlit; + if (mat->Get(AI_MATKEY_GLTF_UNLIT, unlit) == AI_SUCCESS && unlit) { + mAsset->extensionsUsed.KHR_materials_unlit = true; + m->unlit = true; + } } } diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 2bcf8b5de..f478ca487 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -281,6 +281,9 @@ static aiMaterial* ImportMaterial(std::vector& embeddedTexIdxs, Asset& r, M SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.specularGlossinessTexture, aimat, aiTextureType_SPECULAR); } + if (mat.unlit) { + aimat->AddProperty(&mat.unlit, 1, AI_MATKEY_GLTF_UNLIT); + } return aimat; } diff --git a/include/assimp/pbrmaterial.h b/include/assimp/pbrmaterial.h index cd9b5e2bf..723957300 100644 --- a/include/assimp/pbrmaterial.h +++ b/include/assimp/pbrmaterial.h @@ -56,6 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_MATKEY_GLTF_ALPHACUTOFF "$mat.gltf.alphaCutoff", 0, 0 #define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS "$mat.gltf.pbrSpecularGlossiness", 0, 0 #define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR "$mat.gltf.pbrMetallicRoughness.glossinessFactor", 0, 0 +#define AI_MATKEY_GLTF_UNLIT "$mat.gltf.unlit", 0, 0 #define _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE "$tex.file.texCoord" #define _AI_MATKEY_GLTF_MAPPINGNAME_BASE "$tex.mappingname" From 6c0553d810b2050e6291c8e0115c18f915ffa29b Mon Sep 17 00:00:00 2001 From: Alexandre Avenel Date: Sat, 19 May 2018 22:02:54 +0200 Subject: [PATCH 219/278] Add mesh name to ValidateDataStructure log --- code/ValidateDataStructure.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/ValidateDataStructure.cpp b/code/ValidateDataStructure.cpp index 51e04b96b..ed6bde724 100644 --- a/code/ValidateDataStructure.cpp +++ b/code/ValidateDataStructure.cpp @@ -369,7 +369,7 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh) // positions must always be there ... if (!pMesh->mNumVertices || (!pMesh->mVertices && !mScene->mFlags)) { - ReportError("The mesh contains no vertices"); + ReportError("The mesh %s contains no vertices", pMesh->mName.C_Str()); } if (pMesh->mNumVertices > AI_MAX_VERTICES) { @@ -386,7 +386,7 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh) // faces, too if (!pMesh->mNumFaces || (!pMesh->mFaces && !mScene->mFlags)) { - ReportError("Mesh contains no faces"); + ReportError("Mesh %s contains no faces", pMesh->mName.C_Str()); } // now check whether the face indexing layout is correct: From 4b5c49b0872e76eb1bd41af63bb3081236c5bb9f Mon Sep 17 00:00:00 2001 From: Alexandre Avenel Date: Sat, 19 May 2018 22:03:59 +0200 Subject: [PATCH 220/278] Add test for issue 1970: STL with empty solid --- test/models/STL/triangle_with_empty_solid.stl | 11 +++++++++++ test/unit/utSTLImportExport.cpp | 10 ++++++++++ 2 files changed, 21 insertions(+) create mode 100644 test/models/STL/triangle_with_empty_solid.stl diff --git a/test/models/STL/triangle_with_empty_solid.stl b/test/models/STL/triangle_with_empty_solid.stl new file mode 100644 index 000000000..2364b792f --- /dev/null +++ b/test/models/STL/triangle_with_empty_solid.stl @@ -0,0 +1,11 @@ +solid testTriangle + facet normal 0.0 0.0 1.0 + outer loop + vertex 1.0 1.0 0.0 + vertex -1.0 1.0 0.0 + vertex 0.0 -1.0 0.0 + endloop + endfacet +endsolid +solid emptySolid +endsolid diff --git a/test/unit/utSTLImportExport.cpp b/test/unit/utSTLImportExport.cpp index 181862560..de1e78a26 100644 --- a/test/unit/utSTLImportExport.cpp +++ b/test/unit/utSTLImportExport.cpp @@ -73,6 +73,16 @@ TEST_F( utSTLImporterExporter, test_with_two_solids ) { EXPECT_NE( nullptr, scene ); } +TEST_F(utSTLImporterExporter, test_with_empty_solid) { + Assimp::Importer importer; + //STL File with empty mesh. We should still be able to import other meshes in this file. ValidateDataStructure should fail. + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/STL/triangle_with_empty_solid.stl", 0); + EXPECT_NE(nullptr, scene); + + const aiScene *scene2 = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/STL/triangle_with_empty_solid.stl", aiProcess_ValidateDataStructure); + EXPECT_EQ(nullptr, scene2); +} + #ifndef ASSIMP_BUILD_NO_EXPORT TEST_F(utSTLImporterExporter, exporterTest) { From 84739fda0abd018a673b948b78999b4a6df0b92d Mon Sep 17 00:00:00 2001 From: Alexandre Avenel Date: Sat, 19 May 2018 22:05:06 +0200 Subject: [PATCH 221/278] Fix #1970: stl with empty solid Log warning instead of stopping whole import. --- code/STLLoader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/STLLoader.cpp b/code/STLLoader.cpp index 46808503d..73a780e34 100644 --- a/code/STLLoader.cpp +++ b/code/STLLoader.cpp @@ -352,7 +352,7 @@ void STLImporter::LoadASCIIFile( aiNode *root ) { if (positionBuffer.empty()) { pMesh->mNumFaces = 0; - throw DeadlyImportError("STL: ASCII file is empty or invalid; no data loaded"); + ASSIMP_LOG_WARN("STL: mesh is empty or invalid; no data loaded"); } if (positionBuffer.size() % 3 != 0) { pMesh->mNumFaces = 0; From 978a7cbeb20c5a4aa0112dc2403379f7fbf84014 Mon Sep 17 00:00:00 2001 From: Alexandre Avenel Date: Mon, 21 May 2018 11:50:19 +0200 Subject: [PATCH 222/278] Fix #1587 : add validation to LWS unit test It seems that the validation is now OK. Also add a bunch of tests to try to import each file we have in this format. --- test/unit/utLWSImportExport.cpp | 84 +++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 3 deletions(-) diff --git a/test/unit/utLWSImportExport.cpp b/test/unit/utLWSImportExport.cpp index dcf456b56..e34cfc90e 100644 --- a/test/unit/utLWSImportExport.cpp +++ b/test/unit/utLWSImportExport.cpp @@ -42,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "UnitTestPCH.h" #include "AbstractImportExportBase.h" +#include #include @@ -52,13 +53,90 @@ class utLWSImportExport : public AbstractImportExportBase { public: virtual bool importerTest() { Assimp::Importer importer; - const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/LWS/move_x.lws", 0 ); + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/LWS/move_x.lws", aiProcess_ValidateDataStructure); return nullptr != scene; - - return true; } }; TEST_F( utLWSImportExport, importLWSFromFileTest ) { EXPECT_TRUE( importerTest() ); } + +TEST_F(utLWSImportExport, importLWSmove_x_post_linear) { + ::Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_x_post_linear.lws", aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); +} + +TEST_F(utLWSImportExport, importLWSmove_xz_bezier) { + ::Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_xz_bezier.lws", aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); +} + +TEST_F(utLWSImportExport, importLWSmove_xz_stepped) { + ::Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_xz_stepped.lws", aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); +} + +TEST_F(utLWSImportExport, importLWSmove_x_oldformat_56) { + ::Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_x_oldformat_56.lws", aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); +} + +TEST_F(utLWSImportExport, importLWSmove_x_post_offset_repeat) { + ::Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_x_post_offset_repeat.lws", aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); +} + +TEST_F(utLWSImportExport, importLWSmove_xz_hermite) { + ::Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_xz_hermite.lws", aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); +} + +TEST_F(utLWSImportExport, importLWSmove_y_pre_ofrep_post_osc) { + ::Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_y_pre_ofrep_post_osc.lws", aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); +} + +TEST_F(utLWSImportExport, importLWSmove_x_oldformat_6) { + ::Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_x_oldformat_6.lws", aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); +} + +TEST_F(utLWSImportExport, importLWSmove_x_post_repeat) { + ::Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_x_post_repeat.lws", aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); +} + +TEST_F(utLWSImportExport, importLWSmove_xz_linear) { + ::Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_xz_linear.lws", aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); +} + +TEST_F(utLWSImportExport, importLWSmove_x_post_constant) { + ::Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_x_post_constant.lws", aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); +} + +TEST_F(utLWSImportExport, importLWSmove_x_post_reset) { + ::Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_x_post_reset.lws", aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); +} + +TEST_F(utLWSImportExport, importLWSmove_xz_spline) { + ::Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWS/move_xz_spline.lws", aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); +} + From 8abcc454ada68ff96f4c373cf1bd64403470021a Mon Sep 17 00:00:00 2001 From: smalcom Date: Mon, 21 May 2018 17:38:01 +0300 Subject: [PATCH 223/278] [F] Uninitialized variables. --- code/D3MFExporter.cpp | 2 +- test/unit/utMetadata.cpp | 2 +- test/unit/utSharedPPData.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/D3MFExporter.cpp b/code/D3MFExporter.cpp index 204e6f77b..99e2ff3f5 100644 --- a/code/D3MFExporter.cpp +++ b/code/D3MFExporter.cpp @@ -222,7 +222,7 @@ void D3MFExporter::writeMetaData() { return; } - const aiString *key; + const aiString *key = nullptr; const aiMetadataEntry *entry(nullptr); for ( size_t i = 0; i < numMetaEntries; ++i ) { mScene->mMetaData->Get( i, key, entry ); diff --git a/test/unit/utMetadata.cpp b/test/unit/utMetadata.cpp index 0801ffd3f..c2cd6e1ef 100644 --- a/test/unit/utMetadata.cpp +++ b/test/unit/utMetadata.cpp @@ -210,7 +210,7 @@ TEST_F( utMetadata, copy_test ) { // int32_t test { - int32_t v; + int32_t v = 0; bool ok = copy.Get( "int32", v ); EXPECT_TRUE( ok ); EXPECT_EQ( i32v, v ); diff --git a/test/unit/utSharedPPData.cpp b/test/unit/utSharedPPData.cpp index a7c3043a5..94f2a5678 100644 --- a/test/unit/utSharedPPData.cpp +++ b/test/unit/utSharedPPData.cpp @@ -78,7 +78,7 @@ TEST_F(SharedPPDataTest, testPODProperty) { int i = 5; shared->AddProperty("test",i); - int o; + int o = 0; EXPECT_TRUE(shared->GetProperty("test",o)); EXPECT_EQ(5, o); EXPECT_FALSE(shared->GetProperty("test2",o)); From 348b34a2de53e14be058f2beadf5d2c506c02104 Mon Sep 17 00:00:00 2001 From: smalcom Date: Mon, 21 May 2018 17:38:43 +0300 Subject: [PATCH 224/278] [F] Wrong type in equation. --- tools/assimp_qt_viewer/mainwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/assimp_qt_viewer/mainwindow.cpp b/tools/assimp_qt_viewer/mainwindow.cpp index d7d809086..ae68a2234 100644 --- a/tools/assimp_qt_viewer/mainwindow.cpp +++ b/tools/assimp_qt_viewer/mainwindow.cpp @@ -301,7 +301,7 @@ QMap exportersMap; return; } - for (int i = 0; i < exporter.GetExportFormatCount(); ++i) + for (size_t i = 0; i < exporter.GetExportFormatCount(); ++i) { const aiExportFormatDesc* desc = exporter.GetExportFormatDescription(i); exportersList.push_back(desc->id + QString(": ") + desc->description); From 7777883fe73bd401777f68e78659c504c48c6cb6 Mon Sep 17 00:00:00 2001 From: Adrian Mark Perez Date: Tue, 22 May 2018 13:55:36 -0700 Subject: [PATCH 225/278] Fix GenVertexNormals --- code/GenVertexNormalsProcess.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/code/GenVertexNormalsProcess.cpp b/code/GenVertexNormalsProcess.cpp index 7f29411c3..f0fb0ba19 100644 --- a/code/GenVertexNormalsProcess.cpp +++ b/code/GenVertexNormalsProcess.cpp @@ -146,7 +146,7 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]]; const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]]; const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]]; - const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)); + const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe(); for (unsigned int i = 0;i < face.mNumIndices;++i) { pMesh->mNormals[face.mIndices[i]] = vNor; @@ -214,17 +214,15 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int vertexFinder->FindPositions( pMesh->mVertices[i] , posEpsilon, verticesFound); aiVector3D vr = pMesh->mNormals[i]; - ai_real vrlen = vr.Length(); aiVector3D pcNor; for (unsigned int a = 0; a < verticesFound.size(); ++a) { aiVector3D v = pMesh->mNormals[verticesFound[a]]; - // check whether the angle between the two normals is not too large - // HACK: if v.x is qnan the dot product will become qnan, too - // therefore the comparison against fLimit should be false - // in every case. - if (v * vr >= fLimit * vrlen * v.Length()) + // Check whether the angle between the two normals is not too large. + // Skip the angle check on our own normal to avoid false negatives + // (v*v is not guaranteed to be 1.0 for all unit vectors v) + if (is_not_qnan(v.x) && (verticesFound[a] == i || (v * vr >= fLimit))) pcNor += v; } pcNew[i] = pcNor.NormalizeSafe(); From 0c07397720bc722cba1af6bf379e72a62b1fb77c Mon Sep 17 00:00:00 2001 From: gstanlo Date: Tue, 22 May 2018 17:32:12 -0700 Subject: [PATCH 226/278] glTF/2.0: Pick scene zero as scene to recursively load if no "scene" property is specified. --- code/glTF2Asset.inl | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index acf8cb331..5aa658f61 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -1216,12 +1216,15 @@ inline void Asset::Load(const std::string& pFile, bool isBinary) // Read the "scene" property, which specifies which scene to load // and recursively load everything referenced by it + unsigned int sceneIndex = 0; if (Value* scene = FindUInt(doc, "scene")) { - unsigned int sceneIndex = scene->GetUint(); + sceneIndex = scene->GetUint(); + } - Ref s = scenes.Retrieve(sceneIndex); - - this->scene = s; + if (Value* scenesArray = FindArray(doc, "scenes")) { + if (sceneIndex < scenesArray->Size()) { + this->scene = scenes.Retrieve(sceneIndex); + } } // Clean up From e201fcf4f43e0fe929aaddb10dce907fed59d839 Mon Sep 17 00:00:00 2001 From: smalcom Date: Thu, 24 May 2018 12:25:27 +0300 Subject: [PATCH 227/278] [-] Function "GetExtension" always return lowercase string. Using uppercase extension in desc is not needed. --- code/3DSLoader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/3DSLoader.cpp b/code/3DSLoader.cpp index 3c95d8193..cd79b0a6d 100644 --- a/code/3DSLoader.cpp +++ b/code/3DSLoader.cpp @@ -71,7 +71,7 @@ static const aiImporterDesc desc = { 0, 0, 0, - "3ds prj 3DS PRJ" + "3ds prj" }; @@ -127,7 +127,7 @@ Discreet3DSImporter::~Discreet3DSImporter() { // Returns whether the class can handle the format of the given file. bool Discreet3DSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const { std::string extension = GetExtension(pFile); - if(extension == "3ds" || extension == "3DS" || extension == "prj"|| extension == "PRJ" ) { + if(extension == "3ds" || extension == "prj") { return true; } From 6093769da1d62fe115b633d6b5ce9f1eacf954a0 Mon Sep 17 00:00:00 2001 From: smalcom Date: Thu, 24 May 2018 12:31:49 +0300 Subject: [PATCH 228/278] [*] Refactoring of "draw axes" procedure. [-] Removed not working part of code for reloading textures. That do nothing, just show checkbox. As Yoda said: "Do. Or do not. There is no try." --- tools/assimp_qt_viewer/glview.cpp | 39 ++++++--------------------- tools/assimp_qt_viewer/glview.hpp | 16 +++++------ tools/assimp_qt_viewer/mainwindow.cpp | 15 +---------- tools/assimp_qt_viewer/mainwindow.hpp | 2 -- 4 files changed, 17 insertions(+), 55 deletions(-) diff --git a/tools/assimp_qt_viewer/glview.cpp b/tools/assimp_qt_viewer/glview.cpp index a9a60a6fc..c52ac34e3 100644 --- a/tools/assimp_qt_viewer/glview.cpp +++ b/tools/assimp_qt_viewer/glview.cpp @@ -560,30 +560,6 @@ void CGLView::Enable_Textures(const bool pEnable) } } -void CGLView::Enable_Axes(const bool pEnable){ - if(pEnable) - { - this->mAxesEnabled = true; - } - else - { - this->mAxesEnabled = false; - } -} - -void CGLView::Enable_Reload_Textures(const bool pEnable) -{ - if(pEnable) - { - this->mReloadTexturesEnabled = true; -// this->mScene->ImportTextures(this->mScene->pScenePath); - } - else - { - this->mReloadTexturesEnabled = false; - } -} - /********************************************************************/ /*********************** Override functions ************************/ /********************************************************************/ @@ -619,7 +595,11 @@ void CGLView::resizeGL(int pWidth, int pHeight) } void CGLView::drawCoordSystem() { - glBindTexture(GL_TEXTURE_1D, 0); + // Disable lighting. Colors must be bright and colorful) + if ( mLightingEnabled ) glDisable( GL_LIGHTING );///TODO: display list + + // For same reason - disable textures. + glBindTexture(GL_TEXTURE_1D, 0); glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_3D, 0); glEnable(GL_COLOR_MATERIAL); @@ -635,6 +615,8 @@ void CGLView::drawCoordSystem() { qglColor(QColor(Qt::yellow)), glVertex3f(0.0, 0.0, 0.0), glVertex3f(0.0, 0.0, -100000.0); qglColor(QColor(Qt::white)); glEnd(); + // Restore previous state of lighting. + if(mLightingEnabled) glEnable(GL_LIGHTING); } void CGLView::paintGL() @@ -651,17 +633,12 @@ void CGLView::paintGL() glTranslatef(-mHelper_Camera.Translation_ToScene.x, -mHelper_Camera.Translation_ToScene.y, -mHelper_Camera.Translation_ToScene.z); glMultMatrixf((GLfloat*)&mHelper_Camera.Rotation_Scene); // Coordinate system - if ( mLightingEnabled ) { - glDisable( GL_LIGHTING );///TODO: display list - } - if (this->mAxesEnabled == true) + if (mScene_AxesEnabled == true) { drawCoordSystem(); } glDisable(GL_COLOR_MATERIAL); - if(mLightingEnabled) glEnable(GL_LIGHTING); - // Scene if(mScene != nullptr) { diff --git a/tools/assimp_qt_viewer/glview.hpp b/tools/assimp_qt_viewer/glview.hpp index 1c397f13f..3bfb8fa08 100644 --- a/tools/assimp_qt_viewer/glview.hpp +++ b/tools/assimp_qt_viewer/glview.hpp @@ -75,9 +75,7 @@ private: }; public: - bool mAxesEnabled = true; - // Textures - bool mReloadTexturesEnabled = false; // If true then textures will reload when the window is activated. + /// \enum ELightType /// Type of light source. enum class ELightType { Directional, Point, Spot }; @@ -146,6 +144,7 @@ private: SBBox mScene_BBox;///< Bounding box of scene. aiVector3D mScene_Center;///< Coordinates of center of the scene. bool mScene_DrawBBox = false;///< Flag which control drawing scene BBox. + bool mScene_AxesEnabled = true;///< Flag which control drawing axes of the coordinate system. // Meshes size_t mHelper_Mesh_Quantity = 0;///< Quantity of meshes in scene. SHelper_Mesh** mHelper_Mesh = nullptr;///< Array of pointers to helper objects for drawing mesh. Sequence of meshes are equivalent to \ref aiScene::mMeshes. @@ -254,7 +253,11 @@ private: /********************************************************************/ protected: + + /// \fn void drawCoordSystem() + /// Draw axes of the coordinate system. void drawCoordSystem(); + /// \fn void initializeGL() override /// Override function to initialise OpenGL. void initializeGL() override; @@ -307,11 +310,8 @@ public: /// \param [in] pEnable - if true then enable textures, false - disable textures. void Enable_Textures(const bool pEnable); - void Enable_Axes(const bool pEnable); - /// \fn void Enable_Textures(const bool pEnable) - /// Control textures drawing. - /// \param [in] pEnable - if true then enable textures, false - disable textures. - void Enable_Reload_Textures(const bool pEnable); + ///TODO: doc + void Enable_Axes(const bool pEnable) { this->mScene_AxesEnabled = pEnable; } /********************************************************************/ /******************** Lighting control functions ********************/ diff --git a/tools/assimp_qt_viewer/mainwindow.cpp b/tools/assimp_qt_viewer/mainwindow.cpp index ae68a2234..cd52230f3 100644 --- a/tools/assimp_qt_viewer/mainwindow.cpp +++ b/tools/assimp_qt_viewer/mainwindow.cpp @@ -48,7 +48,7 @@ QTime time_begin = QTime::currentTime(); ui->cbxLighting->setChecked(true); mGLView->Lighting_Enable(); ui->cbxBBox->setChecked(false); mGLView->Enable_SceneBBox(false); ui->cbxTextures->setChecked(true); mGLView->Enable_Textures(true); - ui->cbxReloadTextures->setChecked(true); mGLView->Enable_Reload_Textures(false); + // // Fill info labels // @@ -195,13 +195,6 @@ GLfloat step; /********************************************************************/ /********************** Constructor/Destructor **********************/ /********************************************************************/ -bool MainWindow::event(QEvent *e) -{ - if (e->type() == QEvent::WindowActivate && this->mGLView->mReloadTexturesEnabled == true) { - qInfo() << "Window Activated"; - } - return QWidget::event(e); -} MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), @@ -378,12 +371,6 @@ void MainWindow::on_cbxDrawAxes_clicked(bool checked) mGLView->updateGL(); } -void MainWindow::on_cbxReloadTextures_clicked(bool checked) -{ - mGLView->Enable_Reload_Textures(checked); - mGLView->updateGL(); -} - void MainWindow::on_cbxTextures_clicked(bool checked) { mGLView->Enable_Textures(checked); diff --git a/tools/assimp_qt_viewer/mainwindow.hpp b/tools/assimp_qt_viewer/mainwindow.hpp index da8a852ac..14e870f51 100644 --- a/tools/assimp_qt_viewer/mainwindow.hpp +++ b/tools/assimp_qt_viewer/mainwindow.hpp @@ -90,7 +90,6 @@ protected: /// \param [in] pEvent - pointer to event data. void keyPressEvent(QKeyEvent* pEvent) override; - bool event(QEvent*); public: /********************************************************************/ @@ -134,5 +133,4 @@ private slots: void on_cbxBBox_clicked(bool checked); void on_cbxTextures_clicked(bool checked); void on_cbxDrawAxes_clicked(bool checked); - void on_cbxReloadTextures_clicked(bool checked); }; From c23f99919673331bb578846c25068568ae86bc86 Mon Sep 17 00:00:00 2001 From: smalcom Date: Thu, 24 May 2018 12:34:18 +0300 Subject: [PATCH 229/278] [+] QtCreator temporary file. --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index f8dda3e8b..60884061d 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,8 @@ build bin/ lib/ +# QtCreator +CMakeLists.txt.user # Generated assimp.pc From f56432f713f9cfa99210db2f050ea850b51be74e Mon Sep 17 00:00:00 2001 From: smalcom Date: Thu, 24 May 2018 13:04:39 +0300 Subject: [PATCH 230/278] [F] One alignment for labels. [-] Unused checkbox. --- tools/assimp_qt_viewer/mainwindow.ui | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/tools/assimp_qt_viewer/mainwindow.ui b/tools/assimp_qt_viewer/mainwindow.ui index 9b139bafd..04208f585 100644 --- a/tools/assimp_qt_viewer/mainwindow.ui +++ b/tools/assimp_qt_viewer/mainwindow.ui @@ -302,6 +302,9 @@ + + Qt::AlignCenter + @@ -312,6 +315,9 @@ + + Qt::AlignCenter + @@ -325,6 +331,9 @@ + + Qt::AlignCenter + @@ -335,6 +344,9 @@ + + Qt::AlignCenter + @@ -349,6 +361,9 @@ + + Qt::AlignCenter + @@ -511,13 +526,6 @@ - - - - Live Reload Textures - - - From fd7f07068c2f173037e2f606f7308421ff6dc5fe Mon Sep 17 00:00:00 2001 From: smalcom Date: Thu, 24 May 2018 13:05:50 +0300 Subject: [PATCH 231/278] [F] React on mouse pressing ig view only. --- tools/assimp_qt_viewer/mainwindow.cpp | 64 ++++++++++++++++----------- tools/assimp_qt_viewer/mainwindow.hpp | 1 + 2 files changed, 40 insertions(+), 25 deletions(-) diff --git a/tools/assimp_qt_viewer/mainwindow.cpp b/tools/assimp_qt_viewer/mainwindow.cpp index cd52230f3..2d87005a0 100644 --- a/tools/assimp_qt_viewer/mainwindow.cpp +++ b/tools/assimp_qt_viewer/mainwindow.cpp @@ -128,40 +128,54 @@ void MainWindow::LogError(const QString& pMessage) void MainWindow::mousePressEvent(QMouseEvent* pEvent) { - if(pEvent->button() & Qt::LeftButton) - mPosition_Pressed_LMB = pEvent->pos(); - else if(pEvent->button() & Qt::RightButton) - mPosition_Pressed_RMB = pEvent->pos(); +const QPoint ms_pt = pEvent->pos(); + + // Check if GLView is pointed. + if(childAt(ms_pt) == mGLView) + { + mPosition_Pressed_Valid = true; + if(pEvent->button() & Qt::LeftButton) + mPosition_Pressed_LMB = ms_pt; + else if(pEvent->button() & Qt::RightButton) + mPosition_Pressed_RMB = ms_pt; + } + else + { + mPosition_Pressed_Valid = false; + } } void MainWindow::mouseMoveEvent(QMouseEvent* pEvent) { - if(pEvent->buttons() & Qt::LeftButton) + if(mPosition_Pressed_Valid) { - GLfloat dx = 180 * GLfloat(pEvent->x() - mPosition_Pressed_LMB.x()) / mGLView->width(); - GLfloat dy = 180 * GLfloat(pEvent->y() - mPosition_Pressed_LMB.y()) / mGLView->height(); + if(pEvent->buttons() & Qt::LeftButton) + { + GLfloat dx = 180 * GLfloat(pEvent->x() - mPosition_Pressed_LMB.x()) / mGLView->width(); + GLfloat dy = 180 * GLfloat(pEvent->y() - mPosition_Pressed_LMB.y()) / mGLView->height(); - if(pEvent->modifiers() & Qt::ShiftModifier) - mGLView->Camera_RotateScene(dy, 0, dx);// Rotate around oX and oZ axises. - else - mGLView->Camera_RotateScene(dy, dx, 0);// Rotate around oX and oY axises. + if(pEvent->modifiers() & Qt::ShiftModifier) + mGLView->Camera_RotateScene(dy, 0, dx);// Rotate around oX and oZ axises. + else + mGLView->Camera_RotateScene(dy, dx, 0);// Rotate around oX and oY axises. - mGLView->updateGL(); - mPosition_Pressed_LMB = pEvent->pos(); - } + mGLView->updateGL(); + mPosition_Pressed_LMB = pEvent->pos(); + } - if(pEvent->buttons() & Qt::RightButton) - { - GLfloat dx = 180 * GLfloat(pEvent->x() - mPosition_Pressed_RMB.x()) / mGLView->width(); - GLfloat dy = 180 * GLfloat(pEvent->y() - mPosition_Pressed_RMB.y()) / mGLView->height(); + if(pEvent->buttons() & Qt::RightButton) + { + GLfloat dx = 180 * GLfloat(pEvent->x() - mPosition_Pressed_RMB.x()) / mGLView->width(); + GLfloat dy = 180 * GLfloat(pEvent->y() - mPosition_Pressed_RMB.y()) / mGLView->height(); - if(pEvent->modifiers() & Qt::ShiftModifier) - mGLView->Camera_Rotate(dy, 0, dx);// Rotate around oX and oZ axises. - else - mGLView->Camera_Rotate(dy, dx, 0);// Rotate around oX and oY axises. + if(pEvent->modifiers() & Qt::ShiftModifier) + mGLView->Camera_Rotate(dy, 0, dx);// Rotate around oX and oZ axises. + else + mGLView->Camera_Rotate(dy, dx, 0);// Rotate around oX and oY axises. - mGLView->updateGL(); - mPosition_Pressed_RMB = pEvent->pos(); + mGLView->updateGL(); + mPosition_Pressed_RMB = pEvent->pos(); + } } } @@ -198,7 +212,7 @@ GLfloat step; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), - mScene(nullptr) + mScene(nullptr), mPosition_Pressed_Valid(false) { using namespace Assimp; diff --git a/tools/assimp_qt_viewer/mainwindow.hpp b/tools/assimp_qt_viewer/mainwindow.hpp index 14e870f51..fc31599b7 100644 --- a/tools/assimp_qt_viewer/mainwindow.hpp +++ b/tools/assimp_qt_viewer/mainwindow.hpp @@ -36,6 +36,7 @@ private: CLoggerView* mLoggerView;///< Pointer to logging object. Assimp::Importer mImporter;///< Assimp importer. const aiScene* mScene;///< Pointer to loaded scene (\ref aiScene). + bool mPosition_Pressed_Valid;///< Mouse button pressed on GLView. QPoint mPosition_Pressed_LMB;///< Position where was pressed left mouse button. QPoint mPosition_Pressed_RMB;///< Position where was pressed right mouse button. From e761f13c8042f6a840b8e29e77698046fc0b9a87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20M=C3=B6ller?= Date: Thu, 24 May 2018 12:07:05 +0200 Subject: [PATCH 232/278] does not access undefined memory area anymore. This will fix some Debuggers, which throw an exception, when accessing out-of-bound memory --- code/STLLoader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/STLLoader.cpp b/code/STLLoader.cpp index 73a780e34..b0ace74b6 100644 --- a/code/STLLoader.cpp +++ b/code/STLLoader.cpp @@ -365,10 +365,10 @@ void STLImporter::LoadASCIIFile( aiNode *root ) { pMesh->mNumFaces = static_cast(positionBuffer.size() / 3); pMesh->mNumVertices = static_cast(positionBuffer.size()); pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; - memcpy(pMesh->mVertices, &positionBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D)); + memcpy(pMesh->mVertices, positionBuffer.data(), pMesh->mNumVertices * sizeof(aiVector3D)); positionBuffer.clear(); pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; - memcpy(pMesh->mNormals, &normalBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D)); + memcpy(pMesh->mNormals, normalBuffer.data(), pMesh->mNumVertices * sizeof(aiVector3D)); normalBuffer.clear(); // now copy faces From f59ab5c34f2e464ac247b5185f705959a6e20d42 Mon Sep 17 00:00:00 2001 From: smalcom Date: Thu, 24 May 2018 17:11:21 +0300 Subject: [PATCH 233/278] [F] More correct control by a mouse --- tools/assimp_qt_viewer/glview.cpp | 21 +++++++++--- tools/assimp_qt_viewer/glview.hpp | 23 ++++++++++--- tools/assimp_qt_viewer/mainwindow.cpp | 47 ++++++++++++++++++--------- tools/assimp_qt_viewer/mainwindow.hpp | 19 +++++++++-- 4 files changed, 82 insertions(+), 28 deletions(-) diff --git a/tools/assimp_qt_viewer/glview.cpp b/tools/assimp_qt_viewer/glview.cpp index c52ac34e3..833400c46 100644 --- a/tools/assimp_qt_viewer/glview.cpp +++ b/tools/assimp_qt_viewer/glview.cpp @@ -1073,24 +1073,30 @@ void CGLView::Camera_Set(const size_t pCameraNumber) gluLookAt(hcam.Position.x, hcam.Position.y, hcam.Position.z, hcam.Target.x, hcam.Target.y, hcam.Target.z, up.x, up.y, up.z); } -void CGLView::Camera_RotateScene(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z) +void CGLView::Camera_RotateScene(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z, const aiMatrix4x4* pMatrix_Rotation_Initial) { auto deg2rad = [](const GLfloat pDegree) -> GLfloat { return pDegree * M_PI / 180.0; }; aiMatrix4x4 mat_rot; mat_rot.FromEulerAnglesXYZ(deg2rad(pAngle_X), deg2rad(pAngle_Y), deg2rad(pAngle_Z)); - mHelper_Camera.Rotation_Scene *= mat_rot; + if(pMatrix_Rotation_Initial != nullptr) + mHelper_Camera.Rotation_Scene = *pMatrix_Rotation_Initial * mat_rot; + else + mHelper_Camera.Rotation_Scene *= mat_rot; } -void CGLView::Camera_Rotate(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z) +void CGLView::Camera_Rotate(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z, const aiMatrix4x4* pMatrix_Rotation_Initial) { auto deg2rad = [](const GLfloat pDegree) -> GLfloat { return pDegree * M_PI / 180.0; }; aiMatrix4x4 mat_rot; mat_rot.FromEulerAnglesXYZ(deg2rad(pAngle_X), deg2rad(pAngle_Y), deg2rad(pAngle_Z)); - mHelper_Camera.Rotation_AroundCamera *= mat_rot; + if(pMatrix_Rotation_Initial != nullptr) + mHelper_Camera.Rotation_AroundCamera = *pMatrix_Rotation_Initial * mat_rot; + else + mHelper_Camera.Rotation_AroundCamera *= mat_rot; } void CGLView::Camera_Translate(const GLfloat pTranslate_X, const GLfloat pTranslate_Y, const GLfloat pTranslate_Z) @@ -1100,3 +1106,10 @@ aiVector3D vect_tr(pTranslate_X, pTranslate_Y, pTranslate_Z); vect_tr *= mHelper_Camera.Rotation_AroundCamera; mHelper_Camera.Translation_ToScene += vect_tr; } + +void CGLView::Camera_Matrix(aiMatrix4x4& pRotation_Camera, aiMatrix4x4& pRotation_Scene, aiVector3D& pTranslation_Camera) +{ + pRotation_Camera = mHelper_Camera.Rotation_AroundCamera; + pRotation_Scene = mHelper_Camera.Rotation_Scene; + pTranslation_Camera = mHelper_Camera.Translation_ToScene; +} diff --git a/tools/assimp_qt_viewer/glview.hpp b/tools/assimp_qt_viewer/glview.hpp index 3bfb8fa08..2d8614e21 100644 --- a/tools/assimp_qt_viewer/glview.hpp +++ b/tools/assimp_qt_viewer/glview.hpp @@ -310,7 +310,9 @@ public: /// \param [in] pEnable - if true then enable textures, false - disable textures. void Enable_Textures(const bool pEnable); - ///TODO: doc + /// \fn void Enable_Axes(const bool pEnable) + /// Control axes drawing. + /// \param [in] pEnable - if true then enable axes, false - disable axes. void Enable_Axes(const bool pEnable) { this->mScene_AxesEnabled = pEnable; } /********************************************************************/ @@ -350,19 +352,23 @@ public: /// \param [in] pCamera_Index - index of the camera (\ref aiScene::mCameras). void Camera_Set(const size_t pCameraNumber); - /// \fn void Camera_RotateScene(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z) + /// \fn void Camera_RotateScene(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z, const aiMatrix4x4* pMatrix_Rotation_Initial) /// Rotate scene around axisees. /// \param [in] pAngle_X - specifies the angle of rotation around axis oX, in degrees. /// \param [in] pAngle_Y - specifies the angle of rotation around axis oY, in degrees. /// \param [in] pAngle_Z - specifies the angle of rotation around axis oZ, in degrees. - void Camera_RotateScene(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z); + /// \param [in] pMatrix_Rotation_Initial - matrix from which calculates new transformation matrix. If not set (equal to nullptr) then current transformation matrix + /// will be used. + void Camera_RotateScene(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z, const aiMatrix4x4* pMatrix_Rotation_Initial = nullptr); - /// \fn void Camera_Rotate(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z) + /// \fn void Camera_Rotate(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z, const aiMatrix4x4* pMatrix_Rotation_Initial = nullptr) /// Rotate camera around axisees. /// \param [in] pAngle_X - specifies the angle of rotation around axis oX, in degrees. /// \param [in] pAngle_Y - specifies the angle of rotation around axis oY, in degrees. /// \param [in] pAngle_Z - specifies the angle of rotation around axis oZ, in degrees. - void Camera_Rotate(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z); + /// \param [in] pMatrix_Rotation_Initial - matrix from which calculates new transformation matrix. If not set (equal to nullptr) then current transformation matrix + /// will be used. + void Camera_Rotate(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z, const aiMatrix4x4* pMatrix_Rotation_Initial = nullptr); /// \fn void Camera_Translate(const size_t pTranslate_X, const size_t pTranslate_Y, const size_t pTranslate_Z) /// Translate camera along axises. In local coordinates. @@ -371,6 +377,13 @@ public: /// \param [in] pTranslate_Z - specifies the Z coordinate of translation vector. void Camera_Translate(const GLfloat pTranslate_X, const GLfloat pTranslate_Y, const GLfloat pTranslate_Z); + /// \fn void Camera_Matrix(aiMatrix4x4& pRotation_Camera, aiMatrix4x4& pRotation_Scene, aiVector3D& pTranslation_Camera) + /// Return data about camera position in world. + /// \param [out] pRotation_Camera - rotation matrix which set rotation angles of the scene around camera. + /// \param [out] pRotation_Scene - rotation matrix which set rotation angles of the scene around own center. + /// \param [out] pTranslation_Camera - translation vector from camera to the scene. + void Camera_Matrix(aiMatrix4x4& pRotation_Camera, aiMatrix4x4& pRotation_Scene, aiVector3D& pTranslation_Camera); + signals: /// \fn void Paint_Finished(const size_t pPaintTime, const GLfloat pDistance) diff --git a/tools/assimp_qt_viewer/mainwindow.cpp b/tools/assimp_qt_viewer/mainwindow.cpp index 2d87005a0..c17188472 100644 --- a/tools/assimp_qt_viewer/mainwindow.cpp +++ b/tools/assimp_qt_viewer/mainwindow.cpp @@ -130,51 +130,63 @@ void MainWindow::mousePressEvent(QMouseEvent* pEvent) { const QPoint ms_pt = pEvent->pos(); +__unused aiVector3D temp_v3; + // Check if GLView is pointed. if(childAt(ms_pt) == mGLView) { - mPosition_Pressed_Valid = true; + if(!mMouse_Transformation.Position_Pressed_Valid) + { + mMouse_Transformation.Position_Pressed_Valid = true;// set flag + // Store current transformation matrices. + mGLView->Camera_Matrix(mMouse_Transformation.Rotation_AroundCamera, mMouse_Transformation.Rotation_Scene, temp_v3); + } + if(pEvent->button() & Qt::LeftButton) - mPosition_Pressed_LMB = ms_pt; + mMouse_Transformation.Position_Pressed_LMB = ms_pt; else if(pEvent->button() & Qt::RightButton) - mPosition_Pressed_RMB = ms_pt; + mMouse_Transformation.Position_Pressed_RMB = ms_pt; } else { - mPosition_Pressed_Valid = false; + mMouse_Transformation.Position_Pressed_Valid = false; } } +void MainWindow::mouseReleaseEvent(QMouseEvent *pEvent) +{ + if(pEvent->buttons() == 0) mMouse_Transformation.Position_Pressed_Valid = false; + +} + void MainWindow::mouseMoveEvent(QMouseEvent* pEvent) { - if(mPosition_Pressed_Valid) + if(mMouse_Transformation.Position_Pressed_Valid) { if(pEvent->buttons() & Qt::LeftButton) { - GLfloat dx = 180 * GLfloat(pEvent->x() - mPosition_Pressed_LMB.x()) / mGLView->width(); - GLfloat dy = 180 * GLfloat(pEvent->y() - mPosition_Pressed_LMB.y()) / mGLView->height(); + GLfloat dx = 180 * GLfloat(pEvent->x() - mMouse_Transformation.Position_Pressed_LMB.x()) / mGLView->width(); + GLfloat dy = 180 * GLfloat(pEvent->y() - mMouse_Transformation.Position_Pressed_LMB.y()) / mGLView->height(); if(pEvent->modifiers() & Qt::ShiftModifier) - mGLView->Camera_RotateScene(dy, 0, dx);// Rotate around oX and oZ axises. + mGLView->Camera_RotateScene(dy, 0, dx, &mMouse_Transformation.Rotation_Scene);// Rotate around oX and oZ axises. else - mGLView->Camera_RotateScene(dy, dx, 0);// Rotate around oX and oY axises. + mGLView->Camera_RotateScene(dy, dx, 0, &mMouse_Transformation.Rotation_Scene);// Rotate around oX and oY axises. mGLView->updateGL(); - mPosition_Pressed_LMB = pEvent->pos(); } if(pEvent->buttons() & Qt::RightButton) { - GLfloat dx = 180 * GLfloat(pEvent->x() - mPosition_Pressed_RMB.x()) / mGLView->width(); - GLfloat dy = 180 * GLfloat(pEvent->y() - mPosition_Pressed_RMB.y()) / mGLView->height(); + GLfloat dx = 180 * GLfloat(pEvent->x() - mMouse_Transformation.Position_Pressed_RMB.x()) / mGLView->width(); + GLfloat dy = 180 * GLfloat(pEvent->y() - mMouse_Transformation.Position_Pressed_RMB.y()) / mGLView->height(); if(pEvent->modifiers() & Qt::ShiftModifier) - mGLView->Camera_Rotate(dy, 0, dx);// Rotate around oX and oZ axises. + mGLView->Camera_Rotate(dy, 0, dx, &mMouse_Transformation.Rotation_AroundCamera);// Rotate around oX and oZ axises. else - mGLView->Camera_Rotate(dy, dx, 0);// Rotate around oX and oY axises. + mGLView->Camera_Rotate(dy, dx, 0, &mMouse_Transformation.Rotation_AroundCamera);// Rotate around oX and oY axises. mGLView->updateGL(); - mPosition_Pressed_RMB = pEvent->pos(); } } } @@ -212,10 +224,13 @@ GLfloat step; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), - mScene(nullptr), mPosition_Pressed_Valid(false) + mScene(nullptr) { using namespace Assimp; + // other variables + mMouse_Transformation.Position_Pressed_Valid = false; + ui->setupUi(this); // Create OpenGL widget mGLView = new CGLView(this); diff --git a/tools/assimp_qt_viewer/mainwindow.hpp b/tools/assimp_qt_viewer/mainwindow.hpp index fc31599b7..2eedf18f2 100644 --- a/tools/assimp_qt_viewer/mainwindow.hpp +++ b/tools/assimp_qt_viewer/mainwindow.hpp @@ -36,9 +36,17 @@ private: CLoggerView* mLoggerView;///< Pointer to logging object. Assimp::Importer mImporter;///< Assimp importer. const aiScene* mScene;///< Pointer to loaded scene (\ref aiScene). - bool mPosition_Pressed_Valid;///< Mouse button pressed on GLView. - QPoint mPosition_Pressed_LMB;///< Position where was pressed left mouse button. - QPoint mPosition_Pressed_RMB;///< Position where was pressed right mouse button. + + /// \struct SMouse_Transformation + /// Holds data about transformation of the scene/camera when mouse us used. + struct SMouse_Transformation + { + bool Position_Pressed_Valid;///< Mouse button pressed on GLView. + QPoint Position_Pressed_LMB;///< Position where was pressed left mouse button. + QPoint Position_Pressed_RMB;///< Position where was pressed right mouse button. + aiMatrix4x4 Rotation_AroundCamera;///< Rotation matrix which set rotation angles of the scene around camera. + aiMatrix4x4 Rotation_Scene;///< Rotation matrix which set rotation angles of the scene around own center. + } mMouse_Transformation; /**********************************/ /************ Functions ***********/ @@ -81,6 +89,11 @@ protected: /// \param [in] pEvent - pointer to event data. void mousePressEvent(QMouseEvent* pEvent) override; + /// \fn void mouseReleaseEvent(QMouseEvent *pEvent) override + /// Override function which handles mouse event "button released". + /// \param [in] pEvent - pointer to event data. + void mouseReleaseEvent(QMouseEvent *pEvent) override; + /// \fn void mouseMoveEvent(QMouseEvent* pEvent) override /// Override function which handles mouse event "move". /// \param [in] pEvent - pointer to event data. From 97cecc858a8d2dbedcd1f3517b8dc02f616d5143 Mon Sep 17 00:00:00 2001 From: gstanlo Date: Thu, 24 May 2018 17:25:26 -0700 Subject: [PATCH 234/278] Properly reads in glTF/2.0 sampler address modes. Assimp was returning glTF/2.0 values as address modes instead of aiTextureMapModes. Also modified text glTF/2.0 model's sampler uv address modes to mirror/clamp respectively, and tests for them in the unit test. --- code/glTF2Importer.cpp | 21 +++++++++++++++++-- .../glTF2/BoxTextured-glTF/BoxTextured.gltf | 4 ++-- test/unit/utglTF2ImportExport.cpp | 17 ++++++++++++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index f478ca487..15c338716 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -121,6 +121,21 @@ bool glTF2Importer::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool return false; } +static aiTextureMapMode ConvertWrappingMode(SamplerWrap gltfWrapMode) +{ + switch (gltfWrapMode) { + case SamplerWrap::Mirrored_Repeat: + return aiTextureMapMode_Mirror; + + case SamplerWrap::Clamp_To_Edge: + return aiTextureMapMode_Clamp; + + case SamplerWrap::UNSET: + case SamplerWrap::Repeat: + default: + return aiTextureMapMode_Wrap; + } +} //static void CopyValue(const glTF2::vec3& v, aiColor3D& out) //{ @@ -198,8 +213,10 @@ inline void SetMaterialTextureProperty(std::vector& embeddedTexIdxs, Asset& mat->AddProperty(&name, AI_MATKEY_GLTF_MAPPINGNAME(texType, texSlot)); mat->AddProperty(&id, AI_MATKEY_GLTF_MAPPINGID(texType, texSlot)); - mat->AddProperty(&sampler->wrapS, 1, AI_MATKEY_MAPPINGMODE_U(texType, texSlot)); - mat->AddProperty(&sampler->wrapT, 1, AI_MATKEY_MAPPINGMODE_V(texType, texSlot)); + aiTextureMapMode wrapS = ConvertWrappingMode(sampler->wrapS); + aiTextureMapMode wrapT = ConvertWrappingMode(sampler->wrapT); + mat->AddProperty(&wrapS, 1, AI_MATKEY_MAPPINGMODE_U(texType, texSlot)); + mat->AddProperty(&wrapT, 1, AI_MATKEY_MAPPINGMODE_V(texType, texSlot)); if (sampler->magFilter != SamplerMagFilter::UNSET) { mat->AddProperty(&sampler->magFilter, 1, AI_MATKEY_GLTF_MAPPINGFILTER_MAG(texType, texSlot)); diff --git a/test/models/glTF2/BoxTextured-glTF/BoxTextured.gltf b/test/models/glTF2/BoxTextured-glTF/BoxTextured.gltf index eff658f02..88d65391e 100644 --- a/test/models/glTF2/BoxTextured-glTF/BoxTextured.gltf +++ b/test/models/glTF2/BoxTextured-glTF/BoxTextured.gltf @@ -146,8 +146,8 @@ { "magFilter": 9729, "minFilter": 9986, - "wrapS": 10497, - "wrapT": 10497 + "wrapS": 33648, + "wrapT": 33071 } ], "bufferViews": [ diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp index 58ebe3017..5117a56fc 100644 --- a/test/unit/utglTF2ImportExport.cpp +++ b/test/unit/utglTF2ImportExport.cpp @@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include using namespace Assimp; @@ -54,7 +55,21 @@ public: virtual bool importerTest() { Assimp::Importer importer; const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", aiProcess_ValidateDataStructure); - return nullptr != scene; + EXPECT_NE( scene, nullptr ); + if ( !scene ) return false; + + EXPECT_TRUE( scene->HasMaterials() ); + if ( !scene->HasMaterials() ) return false; + const aiMaterial *material = scene->mMaterials[0]; + + aiString path; + aiTextureMapMode modes[2]; + EXPECT_EQ( aiReturn_SUCCESS, material->GetTexture(aiTextureType_DIFFUSE, 0, &path, nullptr, nullptr, nullptr, nullptr, modes) ); + EXPECT_STREQ( path.C_Str(), "CesiumLogoFlat.png" ); + EXPECT_EQ( modes[0], aiTextureMapMode_Mirror ); + EXPECT_EQ( modes[1], aiTextureMapMode_Clamp ); + + return true; } virtual bool binaryImporterTest() { From d72ff712cb70f8345a3eb02a633c790d719da348 Mon Sep 17 00:00:00 2001 From: smalcom Date: Fri, 25 May 2018 21:16:08 +0300 Subject: [PATCH 235/278] [F] List of importers can be empty. --- code/Importer.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/code/Importer.cpp b/code/Importer.cpp index 139dc6c51..347ce12d2 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -970,15 +970,19 @@ void Importer::GetExtensionList(aiString& szOut) const (*i)->GetExtensionList(str); } - for (std::set::const_iterator it = str.begin();; ) { - szOut.Append("*."); - szOut.Append((*it).c_str()); + // List can be empty + if(str.size() > 0) + { + for (std::set::const_iterator it = str.begin();; ) { + szOut.Append("*."); + szOut.Append((*it).c_str()); - if (++it == str.end()) { - break; - } - szOut.Append(";"); - } + if (++it == str.end()) { + break; + } + szOut.Append(";"); + } + } ASSIMP_END_EXCEPTION_REGION(void); } From 67eff10d8f3197dea997039cdeb63de59825861b Mon Sep 17 00:00:00 2001 From: smalcom Date: Fri, 25 May 2018 21:19:06 +0300 Subject: [PATCH 236/278] [*] qt_assimp_viewer can be built with Qt4 or Qt5. [F] Working in doule precision. --- CMakeLists.txt | 27 +-- tools/assimp_qt_viewer/CMakeLists.txt | 127 ++++++++++---- tools/assimp_qt_viewer/glview.cpp | 233 ++++++++++++++++++++++++-- tools/assimp_qt_viewer/glview.hpp | 16 +- tools/assimp_qt_viewer/mainwindow.cpp | 41 ++++- tools/assimp_qt_viewer/mainwindow.hpp | 6 +- 6 files changed, 370 insertions(+), 80 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cb407c4b1..d5a7bc278 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -412,32 +412,7 @@ IF ( ASSIMP_BUILD_ASSIMP_TOOLS ) ENDIF ( WIN32 AND DirectX_D3DX9_LIBRARY ) ADD_SUBDIRECTORY( tools/assimp_cmd/ ) - - # Check dependencies for assimp_qt_viewer. - # Why here? Maybe user do not want Qt viewer and have no Qt. - # Why assimp_qt_viewer/CMakeLists.txt still contain similar check? - # Because viewer can be build independently of Assimp. - FIND_PACKAGE(Qt5Widgets QUIET) - FIND_PACKAGE(DevIL QUIET) - FIND_PACKAGE(OpenGL QUIET) - IF ( Qt5Widgets_FOUND AND IL_FOUND AND OPENGL_FOUND) - ADD_SUBDIRECTORY( tools/assimp_qt_viewer/ ) - ELSE() - SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "") - IF (NOT Qt5_FOUND) - SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} Qt5") - ENDIF (NOT Qt5_FOUND) - - IF (NOT IL_FOUND) - SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} DevIL") - ENDIF (NOT IL_FOUND) - - IF (NOT OPENGL_FOUND) - SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} OpengGL") - ENDIF (NOT OPENGL_FOUND) - - MESSAGE (WARNING "Build of assimp_qt_viewer is disabled. Unsatisfied dendencies: ${ASSIMP_QT_VIEWER_DEPENDENCIES}") - ENDIF ( Qt5Widgets_FOUND AND IL_FOUND AND OPENGL_FOUND) + ADD_SUBDIRECTORY( tools/assimp_qt_viewer/ ) ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS ) IF ( ASSIMP_BUILD_SAMPLES) diff --git a/tools/assimp_qt_viewer/CMakeLists.txt b/tools/assimp_qt_viewer/CMakeLists.txt index b41291e3d..51a4efad8 100644 --- a/tools/assimp_qt_viewer/CMakeLists.txt +++ b/tools/assimp_qt_viewer/CMakeLists.txt @@ -3,44 +3,103 @@ project(assimp_qt_viewer) cmake_minimum_required(VERSION 2.6) -find_package(Qt5 COMPONENTS Gui Widgets OpenGL REQUIRED) -find_package(DevIL REQUIRED) -find_package(OpenGL REQUIRED) - -include_directories( - ${Qt5Widgets_INCLUDES} - ${Assimp_SOURCE_DIR}/include - ${Assimp_SOURCE_DIR}/code - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_SOURCE_DIR} - ${OPENGL_INCLUDE_DIR} - ${IL_INCLUDE_DIR} +OPTION( ASSIMP_QT4_VIEWER + "Set to ON to enable Qt4 against Qt5 for assimp_qt_viewer" + OFF ) -link_directories(${Assimp_BINARY_DIR}) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pedantic -Wall") +FIND_PACKAGE(DevIL QUIET) +FIND_PACKAGE(OpenGL QUIET) -set(assimp_qt_viewer_SRCS main.cpp loggerview.cpp glview.cpp mainwindow.cpp) -qt5_wrap_ui(UISrcs mainwindow.ui) -qt5_wrap_cpp(MOCrcs mainwindow.hpp glview.hpp) +IF(ASSIMP_QT4_VIEWER) + # Qt4 version + FIND_PACKAGE(Qt4 QUIET) +ELSE(ASSIMP_QT4_VIEWER) + # Qt5 version + FIND_PACKAGE(Qt5 COMPONENTS Gui Widgets OpenGL QUIET) +ENDIF(ASSIMP_QT4_VIEWER) -add_executable(${PROJECT_NAME} ${assimp_qt_viewer_SRCS} ${UISrcs} ${MOCrcs}) -target_link_libraries(${PROJECT_NAME} Qt5::Gui Qt5::Widgets Qt5::OpenGL ${IL_LIBRARIES} ${OPENGL_LIBRARIES} assimp) +SET(VIEWER_BUILD:BOOL FALSE) -if(WIN32) # Check if we are on Windows - if(MSVC) # Check if we are using the Visual Studio compiler - #set_target_properties(TestProject PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS") - elseif(CMAKE_COMPILER_IS_GNUCXX) - # SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mwindows") # Not tested - else() - message(SEND_ERROR "You are using an unsupported Windows compiler! (Not MSVC or GCC)") - endif() -elseif(UNIX) - # Nothing special required -else() - message(SEND_ERROR "You are on an unsupported platform! (Not Win32 or Unix)") -endif() +IF((Qt4_FOUND OR Qt5Widgets_FOUND) AND IL_FOUND AND OPENGL_FOUND) + SET(VIEWER_BUILD TRUE) -set_property(TARGET ${PROJECT_NAME} PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) +ELSE((Qt4_FOUND OR Qt5Widgets_FOUND) AND IL_FOUND AND OPENGL_FOUND) + SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "") -install(TARGETS assimp_qt_viewer DESTINATION "${ASSIMP_BIN_INSTALL_DIR}") + IF(ASSIMP_QT4_VIEWER) + IF (NOT Qt4_FOUND) + SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} Qt4") + ENDIF (NOT Qt4_FOUND) + + ELSE(ASSIMP_QT4_VIEWER) + IF (NOT Qt5_FOUND) + SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} Qt5") + ENDIF (NOT Qt5_FOUND) + + ENDIF(ASSIMP_QT4_VIEWER) + + IF (NOT IL_FOUND) + SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} DevIL") + ENDIF (NOT IL_FOUND) + + IF (NOT OPENGL_FOUND) + SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} OpengGL") + ENDIF (NOT OPENGL_FOUND) + + MESSAGE (WARNING "Build of assimp_qt_viewer is disabled. Unsatisfied dendencies: ${ASSIMP_QT_VIEWER_DEPENDENCIES}") +ENDIF((Qt4_FOUND OR Qt5Widgets_FOUND) AND IL_FOUND AND OPENGL_FOUND) + +IF(VIEWER_BUILD) + INCLUDE_DIRECTORIES( + ${Assimp_SOURCE_DIR}/include + ${Assimp_SOURCE_DIR}/code + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR} + ${OPENGL_INCLUDE_DIR} + ${IL_INCLUDE_DIR} + ) + + LINK_DIRECTORIES(${Assimp_BINARY_DIR}) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pedantic -Wall") + + SET(assimp_qt_viewer_SRCS main.cpp loggerview.cpp glview.cpp mainwindow.cpp) + + IF(ASSIMP_QT4_VIEWER) + MESSAGE("assimp_qt_viewer use Qt4") + ADD_DEFINITIONS( -DASSIMP_QT4_VIEWER ) + INCLUDE_DIRECTORIES(${QT_INCLUDES}) + qt4_wrap_ui(UISrcs mainwindow.ui) + qt4_wrap_cpp(MOCrcs mainwindow.hpp glview.hpp) + ELSE() + MESSAGE("assimp_qt_viewer use Qt5") + INCLUDE_DIRECTORIES(${Qt5Widgets_INCLUDES}) + qt5_wrap_ui(UISrcs mainwindow.ui) + qt5_wrap_cpp(MOCrcs mainwindow.hpp glview.hpp) + ENDIF() + + add_executable(${PROJECT_NAME} ${assimp_qt_viewer_SRCS} ${UISrcs} ${MOCrcs}) + + IF(ASSIMP_QT4_VIEWER) + target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES} ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTOPENGL_LIBRARY} ${IL_LIBRARIES} ${OPENGL_LIBRARIES} assimp) + ELSE() + target_link_libraries(${PROJECT_NAME} Qt5::Gui Qt5::Widgets Qt5::OpenGL ${IL_LIBRARIES} ${OPENGL_LIBRARIES} assimp) + ENDIF() + + IF(WIN32) # Check if we are on Windows + IF(MSVC) # Check if we are using the Visual Studio compiler + #set_target_properties(TestProject PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS") + ELSEIF(CMAKE_COMPILER_IS_GNUCXX) + # SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mwindows") # Not tested + ELSE() + MESSAGE(SEND_ERROR "You are using an unsupported Windows compiler! (Not MSVC or GCC)") + ENDIF() + ELSEIF(UNIX) + # Nothing special required + ELSE() + MESSAGE(SEND_ERROR "You are on an unsupported platform! (Not Win32 or Unix)") + ENDIF() + + SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) + INSTALL(TARGETS assimp_qt_viewer DESTINATION "${ASSIMP_BIN_INSTALL_DIR}") +ENDIF(VIEWER_BUILD) diff --git a/tools/assimp_qt_viewer/glview.cpp b/tools/assimp_qt_viewer/glview.cpp index 833400c46..c67420c06 100644 --- a/tools/assimp_qt_viewer/glview.cpp +++ b/tools/assimp_qt_viewer/glview.cpp @@ -5,6 +5,9 @@ #include "glview.hpp" +// Header files, Qt. +#include + // Header files, OpenGL. #if defined(__APPLE__) # include @@ -58,6 +61,33 @@ void CGLView::SHelper_Camera::SetDefault() /************ CGLView *************/ /**********************************/ +#if !ASSIMP_QT4_VIEWER +# define ConditionalContextControl_Begin \ + bool ContextEnabledHere; \ + \ + if(mGLContext_Current) \ + { \ + ContextEnabledHere = false; \ + } \ + else \ + { \ + makeCurrent(); \ + mGLContext_Current = true; \ + ContextEnabledHere = true; \ + } \ + \ + do {} while(false) + +# define ConditionalContextControl_End \ + if(ContextEnabledHere) \ + { \ + doneCurrent(); \ + mGLContext_Current = false; \ + } \ + \ + do {} while(false) +#endif // ASSIMP_QT4_VIEWER + void CGLView::Material_Apply(const aiMaterial* pMaterial) { GLfloat tcol[4]; @@ -105,7 +135,7 @@ void CGLView::Material_Apply(const aiMaterial* pMaterial) glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, tcol); // Shininess - float shininess, strength; + ai_real shininess, strength; max = 1; ret1 = aiGetMaterialFloatArray(pMaterial, AI_MATKEY_SHININESS, &shininess, &max); @@ -406,10 +436,11 @@ void CGLView::BBox_GetFromVertices(const aiVector3D* pVertices, const size_t pVe for(size_t idx_vert = 1; idx_vert < pVerticesQuantity; idx_vert++) { - const GLfloat x = pVertices[idx_vert].x; - const GLfloat y = pVertices[idx_vert].y; - const GLfloat z = pVertices[idx_vert].z; + const ai_real x = pVertices[idx_vert].x; + const ai_real y = pVertices[idx_vert].y; + const ai_real z = pVertices[idx_vert].z; + printf("vert[%lu]=%g,%g,%g\r\n", idx_vert, x, y, z);///TODO: dbg // search minimal... AssignIfLesser(&pBBox.Minimum.x, x); AssignIfLesser(&pBBox.Minimum.y, y); @@ -439,14 +470,29 @@ void CGLView::LogError(const QString& pMessage) /************************** Draw functions **************************/ /********************************************************************/ +static void print_matrix(const aiMatrix4x4 pMatrix)///TODO: dbg +{ + printf("Matrix:\r\n"); + printf("\t%g,%g,%g%g\r\n", pMatrix.a1, pMatrix.a2, pMatrix.a3, pMatrix.a4); + printf("\t%g,%g,%g%g\r\n", pMatrix.b1, pMatrix.b2, pMatrix.b3, pMatrix.b4); + printf("\t%g,%g,%g%g\r\n", pMatrix.c1, pMatrix.c2, pMatrix.c3, pMatrix.c4); + printf("\t%g,%g,%g%g\r\n", pMatrix.d1, pMatrix.d2, pMatrix.d3, pMatrix.d4); +} + void CGLView::Draw_Node(const aiNode* pNode) { aiMatrix4x4 mat_node = pNode->mTransformation; // Apply node transformation matrix. mat_node.Transpose(); + print_matrix(mat_node); glPushMatrix(); +#if ASSIMP_DOUBLE_PRECISION + glMultMatrixd((GLdouble*)mat_node[0]); +#else glMultMatrixf((GLfloat*)&mat_node); +#endif // ASSIMP_DOUBLE_PRECISION + // Draw all meshes assigned to this node for(size_t idx_mesh_arr = 0; idx_mesh_arr < pNode->mNumMeshes; idx_mesh_arr++) Draw_Mesh(pNode->mMeshes[idx_mesh_arr]); @@ -473,13 +519,21 @@ void CGLView::Draw_Mesh(const size_t pMesh_Index) // Vertices array // glEnableClientState(GL_VERTEX_ARRAY); +#if ASSIMP_DOUBLE_PRECISION + glVertexPointer(3, GL_DOUBLE, 0, mesh_cur.mVertices); +#else glVertexPointer(3, GL_FLOAT, 0, mesh_cur.mVertices); +#endif // ASSIMP_DOUBLE_PRECISION if(mesh_cur.HasVertexColors(0)) { glEnable(GL_COLOR_MATERIAL);///TODO: cache glEnableClientState(GL_COLOR_ARRAY); +#if ASSIMP_DOUBLE_PRECISION + glColorPointer(4, GL_DOUBLE, 0, mesh_cur.mColors[0]); +#else glColorPointer(4, GL_FLOAT, 0, mesh_cur.mColors[0]); +#endif // ASSIMP_DOUBLE_PRECISION } // @@ -488,7 +542,11 @@ void CGLView::Draw_Mesh(const size_t pMesh_Index) if(mesh_cur.HasTextureCoords(0)) { glEnableClientState(GL_TEXTURE_COORD_ARRAY); +#if ASSIMP_DOUBLE_PRECISION + glTexCoordPointer(2, GL_DOUBLE, sizeof(aiVector3D), mesh_cur.mTextureCoords[0]); +#else glTexCoordPointer(2, GL_FLOAT, sizeof(aiVector3D), mesh_cur.mTextureCoords[0]); +#endif // ASSIMP_DOUBLE_PRECISION } // @@ -497,7 +555,11 @@ void CGLView::Draw_Mesh(const size_t pMesh_Index) if(mesh_cur.HasNormals()) { glEnableClientState(GL_NORMAL_ARRAY); +#if ASSIMP_DOUBLE_PRECISION + glNormalPointer(GL_DOUBLE, 0, mesh_cur.mNormals); +#else glNormalPointer(GL_FLOAT, 0, mesh_cur.mNormals); +#endif // ASSIMP_DOUBLE_PRECISION } // @@ -530,22 +592,46 @@ void CGLView::Draw_BBox(const SBBox& pBBox) glBindTexture(GL_TEXTURE_1D, 0); glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_3D, 0); +#if ASSIMP_QT4_VIEWER qglColor(QColor(Qt::white)); +#else + const QColor c_w(Qt::white); + + glColor3f(c_w.redF(), c_w.greenF(), c_w.blueF()); +#endif // ASSIMP_QT4_VIEWER + glBegin(GL_LINE_STRIP); +# if ASSIMP_DOUBLE_PRECISION + glVertex3dv(&vertex[0][0]), glVertex3dv(&vertex[1][0]), glVertex3dv(&vertex[2][0]), glVertex3dv(&vertex[3][0]), glVertex3dv(&vertex[0][0]);// "Minimum" side. + glVertex3dv(&vertex[4][0]), glVertex3dv(&vertex[5][0]), glVertex3dv(&vertex[6][0]), glVertex3dv(&vertex[7][0]), glVertex3dv(&vertex[4][0]);// Edge and "maximum" side. +# else glVertex3fv(&vertex[0][0]), glVertex3fv(&vertex[1][0]), glVertex3fv(&vertex[2][0]), glVertex3fv(&vertex[3][0]), glVertex3fv(&vertex[0][0]);// "Minimum" side. glVertex3fv(&vertex[4][0]), glVertex3fv(&vertex[5][0]), glVertex3fv(&vertex[6][0]), glVertex3fv(&vertex[7][0]), glVertex3fv(&vertex[4][0]);// Edge and "maximum" side. +# endif // ASSIMP_DOUBLE_PRECISION glEnd(); + glBegin(GL_LINES); +# if ASSIMP_DOUBLE_PRECISION + glVertex3dv(&vertex[1][0]), glVertex3dv(&vertex[5][0]); + glVertex3dv(&vertex[2][0]), glVertex3dv(&vertex[6][0]); + glVertex3dv(&vertex[3][0]), glVertex3dv(&vertex[7][0]); +# else glVertex3fv(&vertex[1][0]), glVertex3fv(&vertex[5][0]); glVertex3fv(&vertex[2][0]), glVertex3fv(&vertex[6][0]); glVertex3fv(&vertex[3][0]), glVertex3fv(&vertex[7][0]); +# endif // ASSIMP_DOUBLE_PRECISION glEnd(); glDisable(GL_COLOR_MATERIAL); if(mLightingEnabled) glEnable(GL_LIGHTING); + } void CGLView::Enable_Textures(const bool pEnable) { +#if !ASSIMP_QT4_VIEWER + ConditionalContextControl_Begin; +#endif // ASSIMP_QT4_VIEWER + if(pEnable) { glEnable(GL_TEXTURE_1D); @@ -558,6 +644,10 @@ void CGLView::Enable_Textures(const bool pEnable) glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_3D); } + +#if !ASSIMP_QT4_VIEWER + ConditionalContextControl_End; +#endif // ASSIMP_QT4_VIEWER } /********************************************************************/ @@ -566,7 +656,13 @@ void CGLView::Enable_Textures(const bool pEnable) void CGLView::initializeGL() { +#if ASSIMP_QT4_VIEWER qglClearColor(Qt::gray); +#else + mGLContext_Current = true; + initializeOpenGLFunctions(); + glClearColor(0.5f, 0.5f, 0.5f, 1.0f); +#endif // ASSIMP_QT4_VIEWER glShadeModel(GL_SMOOTH); glEnable(GL_DEPTH_TEST); @@ -583,15 +679,25 @@ void CGLView::initializeGL() glCullFace(GL_BACK); glFrontFace(GL_CCW); + +#if !ASSIMP_QT4_VIEWER + mGLContext_Current = false; +#endif // ASSIMP_QT4_VIEWER } void CGLView::resizeGL(int pWidth, int pHeight) { +#if !ASSIMP_QT4_VIEWER + mGLContext_Current = true; +#endif // ASSIMP_QT4_VIEWER mCamera_Viewport_AspectRatio = (GLdouble)pWidth / pHeight; glViewport(0, 0, pWidth, pHeight); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(mCamera_FOVY, mCamera_Viewport_AspectRatio, 1.0, 100000.0);///TODO: znear/zfar depend on scene size. +#if !ASSIMP_QT4_VIEWER + mGLContext_Current = false; +#endif // ASSIMP_QT4_VIEWER } void CGLView::drawCoordSystem() { @@ -604,7 +710,8 @@ void CGLView::drawCoordSystem() { glBindTexture(GL_TEXTURE_3D, 0); glEnable(GL_COLOR_MATERIAL); glBegin(GL_LINES); - // X, -X +#if ASSIMP_QT4_VIEWER + // X, -X qglColor(QColor(Qt::red)), glVertex3f(0.0, 0.0, 0.0), glVertex3f(100000.0, 0.0, 0.0); qglColor(QColor(Qt::cyan)), glVertex3f(0.0, 0.0, 0.0), glVertex3f(-100000.0, 0.0, 0.0); // Y, -Y @@ -614,14 +721,31 @@ void CGLView::drawCoordSystem() { qglColor(QColor(Qt::blue)), glVertex3f(0.0, 0.0, 0.0), glVertex3f(0.0, 0.0, 100000.0); qglColor(QColor(Qt::yellow)), glVertex3f(0.0, 0.0, 0.0), glVertex3f(0.0, 0.0, -100000.0); qglColor(QColor(Qt::white)); - glEnd(); +#else + // X, -X + glColor3f(1.0f, 0.0f, 0.0f), glVertex3f(0.0, 0.0, 0.0), glVertex3f(100000.0, 0.0, 0.0); + glColor3f(0.5f, 0.5f, 1.0f), glVertex3f(0.0, 0.0, 0.0), glVertex3f(-100000.0, 0.0, 0.0); + // Y, -Y + glColor3f(0.0f, 1.0f, 0.0f), glVertex3f(0.0, 0.0, 0.0), glVertex3f(0.0, 100000.0, 0.0); + glColor3f(1.0f, 0.0f, 1.0f), glVertex3f(0.0, 0.0, 0.0), glVertex3f(0.0, -100000.0, 0.0); + // Z, -Z + glColor3f(0.0f, 0.0f, 1.0f), glVertex3f(0.0, 0.0, 0.0), glVertex3f(0.0, 0.0, 100000.0); + glColor3f(1.0f, 1.0f, 0.0f), glVertex3f(0.0, 0.0, 0.0), glVertex3f(0.0, 0.0, -100000.0); + glColor3f(1.0f, 1.0f, 1.0f); +#endif // ASSIMP_QT4_VIEWER + glEnd(); // Restore previous state of lighting. if(mLightingEnabled) glEnable(GL_LIGHTING); + } void CGLView::paintGL() { - QTime time_paintbegin; +#if !ASSIMP_QT4_VIEWER + mGLContext_Current = true; +#endif // ASSIMP_QT4_VIEWER + + QTime time_paintbegin; time_paintbegin = QTime::currentTime(); @@ -629,9 +753,16 @@ void CGLView::paintGL() glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // Apply current camera transformations. +#if ASSIMP_DOUBLE_PRECISION + glMultMatrixd((GLdouble*)&mHelper_Camera.Rotation_AroundCamera); + glTranslated(-mHelper_Camera.Translation_ToScene.x, -mHelper_Camera.Translation_ToScene.y, -mHelper_Camera.Translation_ToScene.z); + glMultMatrixd((GLdouble*)&mHelper_Camera.Rotation_Scene); +#else glMultMatrixf((GLfloat*)&mHelper_Camera.Rotation_AroundCamera); glTranslatef(-mHelper_Camera.Translation_ToScene.x, -mHelper_Camera.Translation_ToScene.y, -mHelper_Camera.Translation_ToScene.z); glMultMatrixf((GLfloat*)&mHelper_Camera.Rotation_Scene); +#endif // ASSIMP_DOUBLE_PRECISION + // Coordinate system if (mScene_AxesEnabled == true) { @@ -645,9 +776,13 @@ void CGLView::paintGL() Draw_Node(mScene->mRootNode); // Scene BBox if(mScene_DrawBBox) Draw_BBox(mScene_BBox); + } emit Paint_Finished((size_t)time_paintbegin.msecsTo(QTime::currentTime()), mHelper_Camera.Translation_ToScene.Length()); +#if !ASSIMP_QT4_VIEWER + mGLContext_Current = false; +#endif // ASSIMP_QT4_VIEWER } /********************************************************************/ @@ -655,10 +790,12 @@ void CGLView::paintGL() /********************************************************************/ CGLView::CGLView(QWidget *pParent) +#if ASSIMP_QT4_VIEWER : QGLWidget(QGLFormat(QGL::DoubleBuffer | QGL::DepthBuffer), pParent) +#else + : QOpenGLWidget(pParent), mGLContext_Current(false) +#endif // ASSIMP_QT4_VIEWER { - static_assert(sizeof(GLfloat) == sizeof(ai_real), "ai_real in Assimp must be equal to GLfloat/float.");///TODO: may be templates can be used. - // set initial view mHelper_CameraDefault.SetDefault(); Camera_Set(0); @@ -675,6 +812,10 @@ CGLView::~CGLView() void CGLView::FreeScene() { +#if !ASSIMP_QT4_VIEWER + ConditionalContextControl_Begin; +#endif // ASSIMP_QT4_VIEWER + // Set scene to null and after that \ref paintGL will not try to render it. mScene = nullptr; // Clean helper objects. @@ -704,10 +845,18 @@ void CGLView::FreeScene() mTexture_IDMap.clear(); delete [] id_tex; } + +#if !ASSIMP_QT4_VIEWER + ConditionalContextControl_End; +#endif // ASSIMP_QT4_VIEWER } void CGLView::SetScene(const aiScene *pScene, const QString& pScenePath) { +#if !ASSIMP_QT4_VIEWER + ConditionalContextControl_Begin; +#endif // ASSIMP_QT4_VIEWER + FreeScene();// Clear old data // Why checking here, not at begin of function. Because old scene may not exist at know. So, need cleanup. if(pScene == nullptr) return; @@ -934,6 +1083,10 @@ void CGLView::SetScene(const aiScene *pScene, const QString& pScenePath) emit SceneObject_Camera(mScene->mCameras[idx_cam]->mName.C_Str()); } }// if(!mScene->HasCameras()) else + +#if !ASSIMP_QT4_VIEWER + ConditionalContextControl_End; +#endif // ASSIMP_QT4_VIEWER } /********************************************************************/ @@ -942,39 +1095,65 @@ void CGLView::SetScene(const aiScene *pScene, const QString& pScenePath) void CGLView::Lighting_Enable() { +#if !ASSIMP_QT4_VIEWER + ConditionalContextControl_Begin; +#endif // ASSIMP_QT4_VIEWER + mLightingEnabled = true; glEnable(GL_LIGHTING); + +#if !ASSIMP_QT4_VIEWER + ConditionalContextControl_End; +#endif // ASSIMP_QT4_VIEWER } void CGLView::Lighting_Disable() { +#if !ASSIMP_QT4_VIEWER + ConditionalContextControl_Begin; +#endif // ASSIMP_QT4_VIEWER + glDisable(GL_LIGHTING); mLightingEnabled = false; + +#if !ASSIMP_QT4_VIEWER + ConditionalContextControl_End; +#endif // ASSIMP_QT4_VIEWER } void CGLView::Lighting_EditSource(const size_t pLightNumber, const SLightParameters& pLightParameters) { +#if !ASSIMP_QT4_VIEWER + ConditionalContextControl_Begin; +#endif // ASSIMP_QT4_VIEWER + const size_t light_num = GL_LIGHT0 + pLightNumber; GLfloat farr[4]; if(pLightNumber >= GL_MAX_LIGHTS) return;///TODO: return value; - glLightfv(light_num, GL_AMBIENT, &pLightParameters.Ambient.r);// Ambient color - glLightfv(light_num, GL_DIFFUSE, &pLightParameters.Diffuse.r);// Diffuse color - glLightfv(light_num, GL_SPECULAR, &pLightParameters.Specular.r);// Specular color + // Ambient color + farr[0] = pLightParameters.Ambient.r, farr[1] = pLightParameters.Ambient.g; farr[2] = pLightParameters.Ambient.b; farr[3] = pLightParameters.Ambient.a; + glLightfv(light_num, GL_AMBIENT, farr); + // Diffuse color + farr[0] = pLightParameters.Diffuse.r, farr[1] = pLightParameters.Diffuse.g; farr[2] = pLightParameters.Diffuse.b; farr[3] = pLightParameters.Diffuse.a; + glLightfv(light_num, GL_DIFFUSE, farr); + // Specular color + farr[0] = pLightParameters.Specular.r, farr[1] = pLightParameters.Specular.g; farr[2] = pLightParameters.Specular.b; farr[3] = pLightParameters.Specular.a; + glLightfv(light_num, GL_SPECULAR, farr); // Other parameters switch(pLightParameters.Type) { case aiLightSource_DIRECTIONAL: // Direction - farr[0] = pLightParameters.For.Directional.Direction.x, farr[2] = pLightParameters.For.Directional.Direction.y; + farr[0] = pLightParameters.For.Directional.Direction.x, farr[1] = pLightParameters.For.Directional.Direction.y; farr[2] = pLightParameters.For.Directional.Direction.z; farr[3] = 0; glLightfv(light_num, GL_POSITION, farr); break; case aiLightSource_POINT: // Position - farr[0] = pLightParameters.For.Point.Position.x, farr[2] = pLightParameters.For.Point.Position.y; + farr[0] = pLightParameters.For.Point.Position.x, farr[1] = pLightParameters.For.Point.Position.y; farr[2] = pLightParameters.For.Point.Position.z; farr[3] = 1; glLightfv(light_num, GL_POSITION, farr); // Attenuation @@ -985,20 +1164,20 @@ GLfloat farr[4]; break; case aiLightSource_SPOT: // Position - farr[0] = pLightParameters.For.Spot.Position.x, farr[2] = pLightParameters.For.Spot.Position.y, farr[2] = pLightParameters.For.Spot.Position.z; farr[3] = 1; + farr[0] = pLightParameters.For.Spot.Position.x, farr[1] = pLightParameters.For.Spot.Position.y, farr[2] = pLightParameters.For.Spot.Position.z; farr[3] = 1; glLightfv(light_num, GL_POSITION, farr); // Attenuation glLightf(light_num, GL_CONSTANT_ATTENUATION, pLightParameters.For.Spot.Attenuation_Constant); glLightf(light_num, GL_LINEAR_ATTENUATION, pLightParameters.For.Spot.Attenuation_Linear); glLightf(light_num, GL_QUADRATIC_ATTENUATION, pLightParameters.For.Spot.Attenuation_Quadratic); // Spot specific - farr[0] = pLightParameters.For.Spot.Direction.x, farr[2] = pLightParameters.For.Spot.Direction.y, farr[2] = pLightParameters.For.Spot.Direction.z; farr[3] = 0; + farr[0] = pLightParameters.For.Spot.Direction.x, farr[1] = pLightParameters.For.Spot.Direction.y, farr[2] = pLightParameters.For.Spot.Direction.z; farr[3] = 0; glLightfv(light_num, GL_SPOT_DIRECTION, farr); glLightf(light_num, GL_SPOT_CUTOFF, pLightParameters.For.Spot.CutOff); break; default:// For unknown light source types use point source. // Position - farr[0] = pLightParameters.For.Point.Position.x, farr[2] = pLightParameters.For.Point.Position.y; + farr[0] = pLightParameters.For.Point.Position.x, farr[1] = pLightParameters.For.Point.Position.y; farr[2] = pLightParameters.For.Point.Position.z; farr[3] = 1; glLightfv(light_num, GL_POSITION, farr); // Attenuation @@ -1008,20 +1187,40 @@ GLfloat farr[4]; glLightf(light_num, GL_SPOT_CUTOFF, 180.0); break; }// switch(pLightParameters.Type) + +#if !ASSIMP_QT4_VIEWER + ConditionalContextControl_End; +#endif // ASSIMP_QT4_VIEWER } void CGLView::Lighting_EnableSource(const size_t pLightNumber) { +#if !ASSIMP_QT4_VIEWER + ConditionalContextControl_Begin; +#endif // ASSIMP_QT4_VIEWER + if(pLightNumber >= GL_MAX_LIGHTS) return;///TODO: return value; glEnable(GL_LIGHT0 + pLightNumber); + +#if !ASSIMP_QT4_VIEWER + ConditionalContextControl_End; +#endif // ASSIMP_QT4_VIEWER } void CGLView::Lighting_DisableSource(const size_t pLightNumber) { +#if !ASSIMP_QT4_VIEWER + ConditionalContextControl_Begin; +#endif // ASSIMP_QT4_VIEWER + if(pLightNumber >= GL_MAX_LIGHTS) return;///TODO: return value; glDisable(GL_LIGHT0 + pLightNumber); + +#if !ASSIMP_QT4_VIEWER + ConditionalContextControl_End; +#endif // ASSIMP_QT4_VIEWER } /********************************************************************/ diff --git a/tools/assimp_qt_viewer/glview.hpp b/tools/assimp_qt_viewer/glview.hpp index 2d8614e21..6068e1448 100644 --- a/tools/assimp_qt_viewer/glview.hpp +++ b/tools/assimp_qt_viewer/glview.hpp @@ -6,14 +6,24 @@ #pragma once // Header files, Qt. -#include +#include +#if ASSIMP_QT4_VIEWER +# include +#else +# include +# include +#endif // ASSIMP_QT4_VIEWER // Header files Assimp #include /// \class CGLView /// Class which hold and render scene. +#if ASSIMP_QT4_VIEWER class CGLView : public QGLWidget +#else +class CGLView : public QOpenGLWidget, protected QOpenGLFunctions +#endif // ASSIMP_QT4_VIEWER { Q_OBJECT @@ -139,6 +149,10 @@ public: private: +#if !ASSIMP_QT4_VIEWER + // Qt5 widget has another behavior, so you must to know that you already made context are current. Yes, its a dirty hack. Better decision are welcome. + bool mGLContext_Current;///< Widget's GL-context made current. +#endif // ASSIMP_QT4_VIEWER // Scene const aiScene* mScene = nullptr;///< Copy of pointer to scene (\ref aiScene). SBBox mScene_BBox;///< Bounding box of scene. diff --git a/tools/assimp_qt_viewer/mainwindow.cpp b/tools/assimp_qt_viewer/mainwindow.cpp index c17188472..85a70ba6b 100644 --- a/tools/assimp_qt_viewer/mainwindow.cpp +++ b/tools/assimp_qt_viewer/mainwindow.cpp @@ -84,7 +84,11 @@ QTime time_begin = QTime::currentTime(); mGLView->Camera_Set(0); // Scene is loaded, do first rendering. LogInfo("Scene is ready for rendering."); +#if ASSIMP_QT4_VIEWER mGLView->updateGL(); +#else + mGLView->update(); +#endif // ASSIMP_QT4_VIEWER } else { @@ -173,7 +177,11 @@ void MainWindow::mouseMoveEvent(QMouseEvent* pEvent) else mGLView->Camera_RotateScene(dy, dx, 0, &mMouse_Transformation.Rotation_Scene);// Rotate around oX and oY axises. + #if ASSIMP_QT4_VIEWER mGLView->updateGL(); + #else + mGLView->update(); + #endif // ASSIMP_QT4_VIEWER } if(pEvent->buttons() & Qt::RightButton) @@ -186,7 +194,11 @@ void MainWindow::mouseMoveEvent(QMouseEvent* pEvent) else mGLView->Camera_Rotate(dy, dx, 0, &mMouse_Transformation.Rotation_AroundCamera);// Rotate around oX and oY axises. + #if ASSIMP_QT4_VIEWER mGLView->updateGL(); + #else + mGLView->update(); + #endif // ASSIMP_QT4_VIEWER } } } @@ -215,7 +227,11 @@ GLfloat step; else if(pEvent->key() == Qt::Key_Down) mGLView->Camera_Translate(0, 0, step); +#if ASSIMP_QT4_VIEWER mGLView->updateGL(); +#else + mGLView->update(); +#endif // ASSIMP_QT4_VIEWER } /********************************************************************/ @@ -303,7 +319,6 @@ QString filename, filter; if(!filename.isEmpty()) ImportFile(filename); } - void MainWindow::on_butExport_clicked() { using namespace Assimp; @@ -367,7 +382,11 @@ void MainWindow::on_cbxLighting_clicked(bool pChecked) else mGLView->Lighting_Disable(); +#if ASSIMP_QT4_VIEWER mGLView->updateGL(); +#else + mGLView->update(); +#endif // ASSIMP_QT4_VIEWER } void MainWindow::on_lstLight_itemSelectionChanged() @@ -379,29 +398,49 @@ bool selected = ui->lstLight->isItemSelected(ui->lstLight->currentItem()); else mGLView->Lighting_DisableSource(ui->lstLight->currentRow()); +#if ASSIMP_QT4_VIEWER mGLView->updateGL(); +#else + mGLView->update(); +#endif // ASSIMP_QT4_VIEWER } void MainWindow::on_lstCamera_clicked( const QModelIndex &) { mGLView->Camera_Set(ui->lstLight->currentRow()); +#if ASSIMP_QT4_VIEWER mGLView->updateGL(); +#else + mGLView->update(); +#endif // ASSIMP_QT4_VIEWER } void MainWindow::on_cbxBBox_clicked(bool checked) { mGLView->Enable_SceneBBox(checked); +#if ASSIMP_QT4_VIEWER mGLView->updateGL(); +#else + mGLView->update(); +#endif // ASSIMP_QT4_VIEWER } void MainWindow::on_cbxDrawAxes_clicked(bool checked) { mGLView->Enable_Axes(checked); +#if ASSIMP_QT4_VIEWER mGLView->updateGL(); +#else + mGLView->update(); +#endif // ASSIMP_QT4_VIEWER } void MainWindow::on_cbxTextures_clicked(bool checked) { mGLView->Enable_Textures(checked); +#if ASSIMP_QT4_VIEWER mGLView->updateGL(); +#else + mGLView->update(); +#endif // ASSIMP_QT4_VIEWER } diff --git a/tools/assimp_qt_viewer/mainwindow.hpp b/tools/assimp_qt_viewer/mainwindow.hpp index 2eedf18f2..e0d17181d 100644 --- a/tools/assimp_qt_viewer/mainwindow.hpp +++ b/tools/assimp_qt_viewer/mainwindow.hpp @@ -6,7 +6,11 @@ #pragma once // Header files, Qt. -#include +#if ASSIMP_QT4_VIEWER +# include +#else +# include +#endif // Header files, project. #include "glview.hpp" From 02d2b6e0d8e5dfd43e310fe1774eff4e6a522c0f Mon Sep 17 00:00:00 2001 From: smalcom Date: Fri, 25 May 2018 21:30:59 +0300 Subject: [PATCH 237/278] [F] Get return "like true" when error occured. --- code/glTF2Exporter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index 9e8dfc822..1001a2d94 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -514,9 +514,9 @@ void glTF2Exporter::ExportMaterials() GetMatColor(mat, pbrSG.specularFactor, AI_MATKEY_COLOR_SPECULAR); if (mat->Get(AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR, pbrSG.glossinessFactor) != AI_SUCCESS) { - float shininess; + float shininess; - if (mat->Get(AI_MATKEY_SHININESS, shininess)) { + if (mat->Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS) { pbrSG.glossinessFactor = shininess / 1000; } } From f29af1abc08b2e3d08efa3808f6458bed39e4150 Mon Sep 17 00:00:00 2001 From: smalcom Date: Fri, 25 May 2018 21:31:22 +0300 Subject: [PATCH 238/278] [-] Trace print removed. --- tools/assimp_qt_viewer/glview.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/tools/assimp_qt_viewer/glview.cpp b/tools/assimp_qt_viewer/glview.cpp index c67420c06..85dbbbae1 100644 --- a/tools/assimp_qt_viewer/glview.cpp +++ b/tools/assimp_qt_viewer/glview.cpp @@ -440,7 +440,6 @@ void CGLView::BBox_GetFromVertices(const aiVector3D* pVertices, const size_t pVe const ai_real y = pVertices[idx_vert].y; const ai_real z = pVertices[idx_vert].z; - printf("vert[%lu]=%g,%g,%g\r\n", idx_vert, x, y, z);///TODO: dbg // search minimal... AssignIfLesser(&pBBox.Minimum.x, x); AssignIfLesser(&pBBox.Minimum.y, y); @@ -470,22 +469,12 @@ void CGLView::LogError(const QString& pMessage) /************************** Draw functions **************************/ /********************************************************************/ -static void print_matrix(const aiMatrix4x4 pMatrix)///TODO: dbg -{ - printf("Matrix:\r\n"); - printf("\t%g,%g,%g%g\r\n", pMatrix.a1, pMatrix.a2, pMatrix.a3, pMatrix.a4); - printf("\t%g,%g,%g%g\r\n", pMatrix.b1, pMatrix.b2, pMatrix.b3, pMatrix.b4); - printf("\t%g,%g,%g%g\r\n", pMatrix.c1, pMatrix.c2, pMatrix.c3, pMatrix.c4); - printf("\t%g,%g,%g%g\r\n", pMatrix.d1, pMatrix.d2, pMatrix.d3, pMatrix.d4); -} - void CGLView::Draw_Node(const aiNode* pNode) { aiMatrix4x4 mat_node = pNode->mTransformation; // Apply node transformation matrix. mat_node.Transpose(); - print_matrix(mat_node); glPushMatrix(); #if ASSIMP_DOUBLE_PRECISION glMultMatrixd((GLdouble*)mat_node[0]); From aa18e8a2a5bb85597814084978b8293e651de83d Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 25 May 2018 21:43:39 +0200 Subject: [PATCH 239/278] Update Importer.cpp Make check more expressive. --- code/Importer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/Importer.cpp b/code/Importer.cpp index 347ce12d2..c258f0519 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -971,8 +971,7 @@ void Importer::GetExtensionList(aiString& szOut) const } // List can be empty - if(str.size() > 0) - { + if( !str.empty() ) { for (std::set::const_iterator it = str.begin();; ) { szOut.Append("*."); szOut.Append((*it).c_str()); From b6888962edd5510c71bef6bebccfe96ce435b0ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9verin=20Lemaignan?= Date: Mon, 28 May 2018 23:53:28 +0100 Subject: [PATCH 240/278] [pyassimp] Updated setup.py --- port/PyAssimp/README.md | 4 ++-- port/PyAssimp/setup.py | 12 +++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/port/PyAssimp/README.md b/port/PyAssimp/README.md index 37ecdb65d..056794fa8 100644 --- a/port/PyAssimp/README.md +++ b/port/PyAssimp/README.md @@ -1,5 +1,5 @@ -PyAssimp Readme -=============== +PyAssimp: Python bindings for libassimp +======================================= A simple Python wrapper for Assimp using `ctypes` to access the library. Requires Python >= 2.6. diff --git a/port/PyAssimp/setup.py b/port/PyAssimp/setup.py index 4ccfaf116..8157bf0ef 100644 --- a/port/PyAssimp/setup.py +++ b/port/PyAssimp/setup.py @@ -1,12 +1,22 @@ + #!/usr/bin/env python # -*- coding: utf-8 -*- import os from distutils.core import setup +def readme(): + with open('README.md') as f: + return f.read() + setup(name='pyassimp', - version='4.1.0', + version='4.1.2', license='ISC', description='Python bindings for the Open Asset Import Library (ASSIMP)', + long_description=readme(), url='https://github.com/assimp/assimp', + author='ASSIMP developers', + author_email='assimp-discussions@lists.sourceforge.net', + maintainer='Séverin Lemaignan', + maintainer_email='severin@guakamole.org', packages=['pyassimp'], data_files=[ ('share/pyassimp', ['README.md']), From c12c56d33ee5ff9734f45acf9c884a593d3bb1fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9verin=20Lemaignan?= Date: Tue, 29 May 2018 10:47:40 +0100 Subject: [PATCH 241/278] [pyassimp] README.{md->rst} to please distutils. Bumped to 4.1.3 --- port/PyAssimp/README.md | 94 --------------------------------------- port/PyAssimp/README.rst | 96 ++++++++++++++++++++++++++++++++++++++++ port/PyAssimp/setup.py | 6 +-- 3 files changed, 99 insertions(+), 97 deletions(-) delete mode 100644 port/PyAssimp/README.md create mode 100644 port/PyAssimp/README.rst diff --git a/port/PyAssimp/README.md b/port/PyAssimp/README.md deleted file mode 100644 index 056794fa8..000000000 --- a/port/PyAssimp/README.md +++ /dev/null @@ -1,94 +0,0 @@ -PyAssimp: Python bindings for libassimp -======================================= - -A simple Python wrapper for Assimp using `ctypes` to access the library. -Requires Python >= 2.6. - -Python 3 support is mostly here, but not well tested. - -Note that pyassimp is not complete. Many ASSIMP features are missing. - -USAGE ------ - -### Complete example: 3D viewer - -`pyassimp` comes with a simple 3D viewer that shows how to load and display a 3D -model using a shader-based OpenGL pipeline. - -![Screenshot](3d_viewer_screenshot.png) - -To use it, from within `/port/PyAssimp`: - -``` -$ cd scripts -$ python ./3D-viewer -``` - -You can use this code as starting point in your applications. - -### Writing your own code - -To get started with `pyassimp`, examine the simpler `sample.py` script in `scripts/`, -which illustrates the basic usage. All Assimp data structures are wrapped using -`ctypes`. All the data+length fields in Assimp's data structures (such as -`aiMesh::mNumVertices`, `aiMesh::mVertices`) are replaced by simple python -lists, so you can call `len()` on them to get their respective size and access -members using `[]`. - -For example, to load a file named `hello.3ds` and print the first -vertex of the first mesh, you would do (proper error handling -substituted by assertions ...): - -```python - -from pyassimp import * -scene = load('hello.3ds') - -assert len(scene.meshes) -mesh = scene.meshes[0] - -assert len(mesh.vertices) -print(mesh.vertices[0]) - -# don't forget this one, or you will leak! -release(scene) - -``` - -Another example to list the 'top nodes' in a -scene: - -```python - -from pyassimp import * -scene = load('hello.3ds') - -for c in scene.rootnode.children: - print(str(c)) - -release(scene) - -``` - -INSTALL -------- - -Install `pyassimp` by running: - -``` -$ python setup.py install -``` - -PyAssimp requires a assimp dynamic library (`DLL` on windows, -`.so` on linux, `.dynlib` on macOS) in order to work. The default search directories -are: - -- the current directory -- on linux additionally: `/usr/lib`, `/usr/local/lib`, - `/usr/lib/x86_64-linux-gnu` - -To build that library, refer to the Assimp master `INSTALL` -instructions. To look in more places, edit `./pyassimp/helper.py`. -There's an `additional_dirs` list waiting for your entries. - diff --git a/port/PyAssimp/README.rst b/port/PyAssimp/README.rst new file mode 100644 index 000000000..f909e2cd0 --- /dev/null +++ b/port/PyAssimp/README.rst @@ -0,0 +1,96 @@ +PyAssimp: Python bindings for libassimp +======================================= + +A simple Python wrapper for Assimp using ``ctypes`` to access the +library. Requires Python >= 2.6. + +Python 3 support is mostly here, but not well tested. + +Note that pyassimp is not complete. Many ASSIMP features are missing. + +USAGE +----- + +Complete example: 3D viewer +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``pyassimp`` comes with a simple 3D viewer that shows how to load and +display a 3D model using a shader-based OpenGL pipeline. + +.. figure:: 3d_viewer_screenshot.png + :alt: Screenshot + + Screenshot + +To use it, from within ``/port/PyAssimp``: + +:: + + $ cd scripts + $ python ./3D-viewer + +You can use this code as starting point in your applications. + +Writing your own code +~~~~~~~~~~~~~~~~~~~~~ + +To get started with ``pyassimp``, examine the simpler ``sample.py`` +script in ``scripts/``, which illustrates the basic usage. All Assimp +data structures are wrapped using ``ctypes``. All the data+length fields +in Assimp's data structures (such as ``aiMesh::mNumVertices``, +``aiMesh::mVertices``) are replaced by simple python lists, so you can +call ``len()`` on them to get their respective size and access members +using ``[]``. + +For example, to load a file named ``hello.3ds`` and print the first +vertex of the first mesh, you would do (proper error handling +substituted by assertions ...): + +.. code:: python + + + from pyassimp import * + scene = load('hello.3ds') + + assert len(scene.meshes) + mesh = scene.meshes[0] + + assert len(mesh.vertices) + print(mesh.vertices[0]) + + # don't forget this one, or you will leak! + release(scene) + +Another example to list the 'top nodes' in a scene: + +.. code:: python + + + from pyassimp import * + scene = load('hello.3ds') + + for c in scene.rootnode.children: + print(str(c)) + + release(scene) + +INSTALL +------- + +Install ``pyassimp`` by running: + +:: + + $ python setup.py install + +PyAssimp requires a assimp dynamic library (``DLL`` on windows, ``.so`` +on linux, ``.dynlib`` on macOS) in order to work. The default search +directories are: + +- the current directory +- on linux additionally: ``/usr/lib``, ``/usr/local/lib``, + ``/usr/lib/x86_64-linux-gnu`` + +To build that library, refer to the Assimp master ``INSTALL`` +instructions. To look in more places, edit ``./pyassimp/helper.py``. +There's an ``additional_dirs`` list waiting for your entries. diff --git a/port/PyAssimp/setup.py b/port/PyAssimp/setup.py index 8157bf0ef..e19e497f0 100644 --- a/port/PyAssimp/setup.py +++ b/port/PyAssimp/setup.py @@ -4,11 +4,11 @@ import os from distutils.core import setup def readme(): - with open('README.md') as f: + with open('README.rst') as f: return f.read() setup(name='pyassimp', - version='4.1.2', + version='4.1.3', license='ISC', description='Python bindings for the Open Asset Import Library (ASSIMP)', long_description=readme(), @@ -19,7 +19,7 @@ setup(name='pyassimp', maintainer_email='severin@guakamole.org', packages=['pyassimp'], data_files=[ - ('share/pyassimp', ['README.md']), + ('share/pyassimp', ['README.rst']), ('share/examples/pyassimp', ['scripts/' + f for f in os.listdir('scripts/')]) ], requires=['numpy'] From c6eda6729677ae86217248701cd0b24dead4d728 Mon Sep 17 00:00:00 2001 From: Sebastian Maisch Date: Tue, 29 May 2018 13:01:11 +0200 Subject: [PATCH 242/278] Changed assimp to force regeneration of normals. --- code/GenFaceNormalsProcess.cpp | 14 +++++++++++++- code/GenVertexNormalsProcess.cpp | 6 ++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/code/GenFaceNormalsProcess.cpp b/code/GenFaceNormalsProcess.cpp index be726302c..6c222e154 100644 --- a/code/GenFaceNormalsProcess.cpp +++ b/code/GenFaceNormalsProcess.cpp @@ -106,7 +106,8 @@ void GenFaceNormalsProcess::Execute( aiScene* pScene) bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh) { if (NULL != pMesh->mNormals) { - return false; + // return false; + delete[] pMesh->mNormals; } // If the mesh consists of lines and/or points but not of @@ -135,8 +136,19 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh) const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]]; const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]]; const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]]; + + auto pV12 = *pV2 - *pV1; + auto pV31 = *pV3 - *pV1; + const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).Normalize(); + if (std::isnan(vNor.x) || std::isnan(vNor.y) || std::isnan(vNor.z)) { + for (unsigned int i = 0; i < face.mNumIndices; ++i) { + pMesh->mNormals[face.mIndices[i]] = aiVector3D(0.0f, 0.0f, 0.0f); + } + continue; + } + for (unsigned int i = 0;i < face.mNumIndices;++i) { pMesh->mNormals[face.mIndices[i]] = vNor; } diff --git a/code/GenVertexNormalsProcess.cpp b/code/GenVertexNormalsProcess.cpp index f746f3776..e0783b0a2 100644 --- a/code/GenVertexNormalsProcess.cpp +++ b/code/GenVertexNormalsProcess.cpp @@ -112,8 +112,10 @@ void GenVertexNormalsProcess::Execute( aiScene* pScene) // Executes the post processing step on the given imported data. bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int meshIndex) { - if (NULL != pMesh->mNormals) - return false; + if (NULL != pMesh->mNormals) { + delete[] pMesh->mNormals; + } +// return false; // If the mesh consists of lines and/or points but not of // triangles or higher-order polygons the normal vectors From ffb6756d2a2dc690e173b89679335ac99d885f29 Mon Sep 17 00:00:00 2001 From: Tammo Hinrichs Date: Wed, 30 May 2018 14:56:53 +0200 Subject: [PATCH 243/278] FBX: LayeredTextures now work with embedded texture data --- code/FBXConverter.cpp | 80 +++++++++++++++++++++++-------------------- code/FBXConverter.h | 4 +++ 2 files changed, 46 insertions(+), 38 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index c50e88390..9c07e9c58 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -1526,6 +1526,46 @@ unsigned int Converter::ConvertVideo( const Video& video ) return static_cast( textures.size() - 1 ); } +aiString Converter::GetTexturePath(const Texture* tex) +{ + aiString path; + path.Set(tex->RelativeFilename()); + + const Video* media = tex->Media(); + if (media != 0) { + bool textureReady = false; //tells if our texture is ready (if it was loaded or if it was found) + unsigned int index; + + VideoMap::const_iterator it = textures_converted.find(media); + if (it != textures_converted.end()) { + index = (*it).second; + textureReady = true; + } + else { + if (media->ContentLength() > 0) { + index = ConvertVideo(*media); + textures_converted[media] = index; + textureReady = true; + } + } + + // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture), if the texture is ready + if (doc.Settings().useLegacyEmbeddedTextureNaming) { + if (textureReady) { + // TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING" + // In FBX files textures are now stored internally by Assimp with their filename included + // Now Assimp can lookup through the loaded textures after all data is processed + // We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it + // This may occur on this case too, it has to be studied + path.data[0] = '*'; + path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index); + } + } + } + + return path; +} + void Converter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap& textures, const std::string& propName, aiTextureType target, const MeshGeometry* const mesh ) @@ -1538,41 +1578,7 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap& const Texture* const tex = ( *it ).second; if ( tex != 0 ) { - aiString path; - path.Set( tex->RelativeFilename() ); - - const Video* media = tex->Media(); - if (media != 0) { - bool textureReady = false; //tells if our texture is ready (if it was loaded or if it was found) - unsigned int index; - - VideoMap::const_iterator it = textures_converted.find(media); - if (it != textures_converted.end()) { - index = (*it).second; - textureReady = true; - } - else { - if (media->ContentLength() > 0) { - index = ConvertVideo(*media); - textures_converted[media] = index; - textureReady = true; - } - } - - // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture), if the texture is ready - if (doc.Settings().useLegacyEmbeddedTextureNaming) { - if (textureReady) { - // TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING" - // In FBX files textures are now stored internally by Assimp with their filename included - // Now Assimp can lookup through the loaded textures after all data is processed - // We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it - // This may occur on this case too, it has to be studied - path.data[0] = '*'; - path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index); - } - } - } - + aiString path = GetTexturePath(tex); out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, 0 ); aiUVTransform uvTrafo; @@ -1696,9 +1702,7 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const LayeredTextu const Texture* const tex = ( *it ).second->getTexture(texIndex); - aiString path; - path.Set( tex->RelativeFilename() ); - + aiString path = GetTexturePath(tex); out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, texIndex ); aiUVTransform uvTrafo; diff --git a/code/FBXConverter.h b/code/FBXConverter.h index 71d93d339..fca42e8d7 100644 --- a/code/FBXConverter.h +++ b/code/FBXConverter.h @@ -228,6 +228,10 @@ private: // Video -> aiTexture unsigned int ConvertVideo(const Video& video); + // ------------------------------------------------------------------------------------------------ + // convert embedded texture if necessary and return actual texture path + aiString GetTexturePath(const Texture* tex); + // ------------------------------------------------------------------------------------------------ void TrySetTextureProperties(aiMaterial* out_mat, const TextureMap& textures, const std::string& propName, From fceeaa72f4a9f4547adc500f45c69202b9e89188 Mon Sep 17 00:00:00 2001 From: Michael Roer Pedersen Date: Thu, 31 May 2018 15:07:00 +0200 Subject: [PATCH 244/278] FBX animation export: Assimp animation time is already in seconds. Just convert to FBX time. --- code/FBXExporter.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index a942e31bc..2403ca845 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -980,9 +980,13 @@ aiMatrix4x4 get_world_transform(const aiNode* node, const aiScene* scene) int64_t to_ktime(double ticks, const aiAnimation* anim) { if (anim->mTicksPerSecond <= 0) { - return static_cast(ticks) * FBX::SECOND; + return static_cast(ticks * FBX::SECOND); } - return (static_cast(ticks) / static_cast(anim->mTicksPerSecond)) * FBX::SECOND; + return (static_cast(ticks / anim->mTicksPerSecond * FBX::SECOND)); +} + +int64_t to_ktime(double time) { + return (static_cast(time * FBX::SECOND)); } void FBXExporter::WriteObjects () @@ -2089,7 +2093,7 @@ void FBXExporter::WriteObjects () // position/translation for (size_t ki = 0; ki < na->mNumPositionKeys; ++ki) { const aiVectorKey& k = na->mPositionKeys[ki]; - times.push_back(to_ktime(k.mTime, anim)); + times.push_back(to_ktime(k.mTime)); xval.push_back(k.mValue.x); yval.push_back(k.mValue.y); zval.push_back(k.mValue.z); @@ -2103,7 +2107,7 @@ void FBXExporter::WriteObjects () times.clear(); xval.clear(); yval.clear(); zval.clear(); for (size_t ki = 0; ki < na->mNumRotationKeys; ++ki) { const aiQuatKey& k = na->mRotationKeys[ki]; - times.push_back(to_ktime(k.mTime, anim)); + times.push_back(to_ktime(k.mTime)); // TODO: aiQuaternion method to convert to Euler... aiMatrix4x4 m(k.mValue.GetMatrix()); aiVector3D qs, qr, qt; @@ -2121,7 +2125,7 @@ void FBXExporter::WriteObjects () times.clear(); xval.clear(); yval.clear(); zval.clear(); for (size_t ki = 0; ki < na->mNumScalingKeys; ++ki) { const aiVectorKey& k = na->mScalingKeys[ki]; - times.push_back(to_ktime(k.mTime, anim)); + times.push_back(to_ktime(k.mTime)); xval.push_back(k.mValue.x); yval.push_back(k.mValue.y); zval.push_back(k.mValue.z); From 64ba839f47a8198f15a070106413fa6e55c9d610 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 31 May 2018 20:04:48 +0200 Subject: [PATCH 245/278] Update Readme.md Fix the link to the active repo containing the assimp-net-code. --- port/AssimpNET/Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/port/AssimpNET/Readme.md b/port/AssimpNET/Readme.md index d251cecc3..dca57470c 100644 --- a/port/AssimpNET/Readme.md +++ b/port/AssimpNET/Readme.md @@ -1 +1 @@ -See https://code.google.com/p/assimp-net/ and https://github.com/assimp/assimp-net for a Github mirror. \ No newline at end of file +Please check the following github-repo for the source: https://github.com/kebby/assimp-net From 31e75b9d5438ea4de3204555a8741119e41041d2 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 31 May 2018 20:18:17 +0200 Subject: [PATCH 246/278] Update FBXConverter.cpp Replaces a 0 by nullptr. --- code/FBXConverter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 9c07e9c58..981203abb 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -1532,7 +1532,7 @@ aiString Converter::GetTexturePath(const Texture* tex) path.Set(tex->RelativeFilename()); const Video* media = tex->Media(); - if (media != 0) { + if (media != nullptr) { bool textureReady = false; //tells if our texture is ready (if it was loaded or if it was found) unsigned int index; From b176513efaa81b396900568dcf67b9f09a1a203e Mon Sep 17 00:00:00 2001 From: Michael Roer Pedersen Date: Fri, 1 Jun 2018 09:24:53 +0200 Subject: [PATCH 247/278] FBX export. to_ktime ticks was ok. --- .gitignore | 3 +++ code/FBXExporter.cpp | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 60884061d..d3ec794d5 100644 --- a/.gitignore +++ b/.gitignore @@ -87,3 +87,6 @@ lib64/assimp-vc120-mt.exp xcuserdata cmake-build-debug +/.vs +/code/assimp.vcxproj.user +*.user diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index 2403ca845..037520641 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -980,9 +980,9 @@ aiMatrix4x4 get_world_transform(const aiNode* node, const aiScene* scene) int64_t to_ktime(double ticks, const aiAnimation* anim) { if (anim->mTicksPerSecond <= 0) { - return static_cast(ticks * FBX::SECOND); + return static_cast(ticks) * FBX::SECOND; } - return (static_cast(ticks / anim->mTicksPerSecond * FBX::SECOND)); + return (static_cast(ticks) / static_cast(anim->mTicksPerSecond)) * FBX::SECOND; } int64_t to_ktime(double time) { From 4af69dbeb9e528c6f3e4b85ac1147cd68482a35c Mon Sep 17 00:00:00 2001 From: Michael Roer Pedersen Date: Fri, 1 Jun 2018 09:33:28 +0200 Subject: [PATCH 248/278] undo .gitignore --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index d3ec794d5..60884061d 100644 --- a/.gitignore +++ b/.gitignore @@ -87,6 +87,3 @@ lib64/assimp-vc120-mt.exp xcuserdata cmake-build-debug -/.vs -/code/assimp.vcxproj.user -*.user From 6aa32b41a1f64fb03f40bbd902950de3bc158d26 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Fri, 1 Jun 2018 12:05:42 +0300 Subject: [PATCH 249/278] Replace type punning with explicit memcpys --- include/assimp/qnan.h | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/include/assimp/qnan.h b/include/assimp/qnan.h index 6ee3b7ce5..251688989 100644 --- a/include/assimp/qnan.h +++ b/include/assimp/qnan.h @@ -98,8 +98,10 @@ AI_FORCE_INLINE bool is_qnan(float in) // compare against // FIXME: Use stuff instead? I think fpclassify needs C99 - return (reinterpret_cast<_IEEESingle*>(&in)->IEEE.Exp == (1u << 8)-1 && - reinterpret_cast<_IEEESingle*>(&in)->IEEE.Frac); + _IEEESingle temp; + memcpy(&temp, &in, sizeof(float)); + return (temp.IEEE.Exp == (1u << 8)-1 && + temp.IEEE.Frac); } // --------------------------------------------------------------------------- @@ -114,8 +116,10 @@ AI_FORCE_INLINE bool is_qnan(double in) // compare against // FIXME: Use stuff instead? I think fpclassify needs C99 - return (reinterpret_cast<_IEEEDouble*>(&in)->IEEE.Exp == (1u << 11)-1 && - reinterpret_cast<_IEEEDouble*>(&in)->IEEE.Frac); + _IEEEDouble temp; + memcpy(&temp, &in, sizeof(in)); + return (temp.IEEE.Exp == (1u << 11)-1 && + temp.IEEE.Frac); } // --------------------------------------------------------------------------- @@ -125,7 +129,9 @@ AI_FORCE_INLINE bool is_qnan(double in) * @param in Input value */ AI_FORCE_INLINE bool is_special_float(float in) { - return (reinterpret_cast<_IEEESingle*>(&in)->IEEE.Exp == (1u << 8)-1); + _IEEESingle temp; + memcpy(&temp, &in, sizeof(float)); + return (temp.IEEE.Exp == (1u << 8)-1); } // --------------------------------------------------------------------------- @@ -135,7 +141,9 @@ AI_FORCE_INLINE bool is_special_float(float in) * @param in Input value */ AI_FORCE_INLINE bool is_special_float(double in) { - return (reinterpret_cast<_IEEEDouble*>(&in)->IEEE.Exp == (1u << 11)-1); + _IEEESingle temp; + memcpy(&temp, &in, sizeof(float)); + return (temp.IEEE.Exp == (1u << 11)-1); } // --------------------------------------------------------------------------- From bbb60c29f09f2ed378fcbe5063851b476f4bfadc Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Fri, 1 Jun 2018 12:20:16 +0300 Subject: [PATCH 250/278] Fix strict aliasing violation in MaterialSystem --- code/MaterialSystem.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/MaterialSystem.cpp b/code/MaterialSystem.cpp index 97892658f..c8262dff0 100644 --- a/code/MaterialSystem.cpp +++ b/code/MaterialSystem.cpp @@ -354,8 +354,9 @@ aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat, return AI_FAILURE; } // Determine mapping type - aiTextureMapping mapping = aiTextureMapping_UV; - aiGetMaterialInteger(mat,AI_MATKEY_MAPPING(type,index),(int*)&mapping); + int mapping_ = static_cast(aiTextureMapping_UV); + aiGetMaterialInteger(mat,AI_MATKEY_MAPPING(type,index), &mapping_); + aiTextureMapping mapping = static_cast(mapping_); if (_mapping) *_mapping = mapping; From 6788d7b18b284e1efa02e59e91a3dba4b52072f6 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Fri, 1 Jun 2018 12:28:33 +0300 Subject: [PATCH 251/278] 3DS: Fix strict aliasing violations --- code/3DSConverter.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/code/3DSConverter.cpp b/code/3DSConverter.cpp index e07ca4c2d..7ec79ba64 100644 --- a/code/3DSConverter.cpp +++ b/code/3DSConverter.cpp @@ -204,8 +204,9 @@ void CopyTexture(aiMaterial& mat, D3DS::Texture& texture, aiTextureType type) mat.AddProperty( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0)); // Setup the texture mapping mode - mat.AddProperty((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_U(type,0)); - mat.AddProperty((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_V(type,0)); + int mapMode = static_cast(texture.mMapMode); + mat.AddProperty(&mapMode,1,AI_MATKEY_MAPPINGMODE_U(type,0)); + mat.AddProperty(&mapMode,1,AI_MATKEY_MAPPINGMODE_V(type,0)); // Mirroring - double the scaling values // FIXME: this is not really correct ... @@ -313,7 +314,8 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat, case D3DS::Discreet3DS::Blinn : eShading = aiShadingMode_Blinn; break; } - mat.AddProperty( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL); + int eShading_ = static_cast(eShading); + mat.AddProperty(&eShading_, 1, AI_MATKEY_SHADING_MODEL); // DIFFUSE texture if( oldMat.sTexDiffuse.mMapName.length() > 0) From b0b604850207a4bf11bc0b4d4f7ce10538c44cc5 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Fri, 1 Jun 2018 12:37:21 +0300 Subject: [PATCH 252/278] LWOMaterial: Fix strict aliasing violations --- code/LWOMaterial.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/LWOMaterial.cpp b/code/LWOMaterial.cpp index f4f43ced6..15c210460 100644 --- a/code/LWOMaterial.cpp +++ b/code/LWOMaterial.cpp @@ -253,7 +253,8 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex pcMat->AddProperty((int*)&temp,1,AI_MATKEY_TEXOP(type,cur)); // setup the mapping mode - pcMat->AddProperty((int*)&mapping,1,AI_MATKEY_MAPPING(type,cur)); + int mapping_ = static_cast(mapping); + pcMat->AddProperty(&mapping_, 1, AI_MATKEY_MAPPING(type, cur)); // add the u-wrapping temp = (unsigned int)GetMapMode(texture.wrapModeWidth); @@ -365,7 +366,8 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat) } if (surf.mMaximumSmoothAngle <= 0.0) m = aiShadingMode_Flat; - pcMat->AddProperty((int*)&m,1,AI_MATKEY_SHADING_MODEL); + int m_ = static_cast(m); + pcMat->AddProperty(&m_, 1, AI_MATKEY_SHADING_MODEL); // (the diffuse value is just a scaling factor) // If a diffuse texture is set, we set this value to 1.0 From f15dcf7663782e63334dc1c725b9a3ee4a7af7fa Mon Sep 17 00:00:00 2001 From: Sebastian Maisch Date: Fri, 1 Jun 2018 17:32:02 +0200 Subject: [PATCH 253/278] Added forced generation of normals with extra flag. --- code/GenFaceNormalsProcess.cpp | 5 +++-- code/GenFaceNormalsProcess.h | 3 ++- code/GenVertexNormalsProcess.cpp | 18 +++++++++++++++--- code/GenVertexNormalsProcess.h | 1 + include/assimp/postprocess.h | 5 ++++- 5 files changed, 25 insertions(+), 7 deletions(-) diff --git a/code/GenFaceNormalsProcess.cpp b/code/GenFaceNormalsProcess.cpp index 6c222e154..30a26b898 100644 --- a/code/GenFaceNormalsProcess.cpp +++ b/code/GenFaceNormalsProcess.cpp @@ -74,6 +74,7 @@ GenFaceNormalsProcess::~GenFaceNormalsProcess() // Returns whether the processing step is present in the given flag field. bool GenFaceNormalsProcess::IsActive( unsigned int pFlags) const { + force_ = (pFlags & aiProcess_ForceGenNormals) != 0; return (pFlags & aiProcess_GenNormals) != 0; } @@ -106,8 +107,8 @@ void GenFaceNormalsProcess::Execute( aiScene* pScene) bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh) { if (NULL != pMesh->mNormals) { - // return false; - delete[] pMesh->mNormals; + if (force_) delete[] pMesh->mNormals; + else return false; } // If the mesh consists of lines and/or points but not of diff --git a/code/GenFaceNormalsProcess.h b/code/GenFaceNormalsProcess.h index 27ae7acac..e2f41e07f 100644 --- a/code/GenFaceNormalsProcess.h +++ b/code/GenFaceNormalsProcess.h @@ -78,7 +78,8 @@ public: private: - bool GenMeshFaceNormals (aiMesh* pcMesh); + bool GenMeshFaceNormals(aiMesh* pcMesh); + mutable bool force_ = false; }; } // end of namespace Assimp diff --git a/code/GenVertexNormalsProcess.cpp b/code/GenVertexNormalsProcess.cpp index e0783b0a2..74139a646 100644 --- a/code/GenVertexNormalsProcess.cpp +++ b/code/GenVertexNormalsProcess.cpp @@ -72,6 +72,7 @@ GenVertexNormalsProcess::~GenVertexNormalsProcess() { // Returns whether the processing step is present in the given flag field. bool GenVertexNormalsProcess::IsActive( unsigned int pFlags) const { + force_ = (pFlags & aiProcess_ForceGenNormals) != 0; return (pFlags & aiProcess_GenSmoothNormals) != 0; } @@ -113,9 +114,9 @@ void GenVertexNormalsProcess::Execute( aiScene* pScene) bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int meshIndex) { if (NULL != pMesh->mNormals) { - delete[] pMesh->mNormals; + if (force_) delete[] pMesh->mNormals; + else return false; } -// return false; // If the mesh consists of lines and/or points but not of // triangles or higher-order polygons the normal vectors @@ -147,7 +148,18 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]]; const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]]; const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]]; - const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)); + + auto pV12 = *pV2 - *pV1; + auto pV31 = *pV3 - *pV1; + + const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).Normalize(); + + if (std::isnan(vNor.x) || std::isnan(vNor.y) || std::isnan(vNor.z)) { + for (unsigned int i = 0; i < face.mNumIndices; ++i) { + pMesh->mNormals[face.mIndices[i]] = aiVector3D(0.0f, 0.0f, 0.0f); + } + continue; + } for (unsigned int i = 0;i < face.mNumIndices;++i) { pMesh->mNormals[face.mIndices[i]] = vNor; diff --git a/code/GenVertexNormalsProcess.h b/code/GenVertexNormalsProcess.h index 5ab9eb6f5..2efafa302 100644 --- a/code/GenVertexNormalsProcess.h +++ b/code/GenVertexNormalsProcess.h @@ -107,6 +107,7 @@ private: /** Configuration option: maximum smoothing angle, in radians*/ ai_real configMaxAngle; + mutable bool force_ = false; }; } // end of namespace Assimp diff --git a/include/assimp/postprocess.h b/include/assimp/postprocess.h index f6c0833ee..1cb9c72f8 100644 --- a/include/assimp/postprocess.h +++ b/include/assimp/postprocess.h @@ -555,10 +555,13 @@ enum aiPostProcessSteps * of the imported model. And if so, it uses that. */ aiProcess_EmbedTextures = 0x10000000, - + // aiProcess_GenEntityMeshes = 0x100000, // aiProcess_OptimizeAnimations = 0x200000 // aiProcess_FixTexturePaths = 0x200000 + + + aiProcess_ForceGenNormals = 0x20000000, }; From 5f820fb6d6bbf55d33292f6719c9083c10d915c3 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 3 Jun 2018 17:21:46 +0200 Subject: [PATCH 254/278] Update appveyor.yml Add Inno setup path to PATH variable. --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index 3b4b3144e..d574dafa6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -32,6 +32,7 @@ install: - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" set CMAKE_GENERATOR_NAME=Visual Studio 15 2017 - if "%platform%"=="x64" set CMAKE_GENERATOR_NAME=%CMAKE_GENERATOR_NAME% Win64 - cmake %CMAKE_DEFINES% -G "%CMAKE_GENERATOR_NAME%" + - set PATH=%PATH%;"C:\\Program Files (x86)\\Inno Setup 5" - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" iscc packaging\windows-innosetup\script.iss cache: From 90549e9680ced21beea680525a93aadfabb948b6 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 3 Jun 2018 21:29:23 +0200 Subject: [PATCH 255/278] Update script.iss Adapt names of dll only for VS2017 --- packaging/windows-innosetup/script.iss | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/packaging/windows-innosetup/script.iss b/packaging/windows-innosetup/script.iss index 8056e31ac..8debcb494 100644 --- a/packaging/windows-innosetup/script.iss +++ b/packaging/windows-innosetup/script.iss @@ -30,16 +30,12 @@ Name: "help"; Description: "Help Files"; Types: full compact Name: "samples"; Description: "Samples"; Types: full Name: "test"; Description: "Test Models (BSD-licensed)"; Types: full Name: "test_nonbsd"; Description: "Test Models (other (free) licenses)"; Types: full -Name: "pyassimp"; Description: "Python Bindings"; Types: full -Name: "dassimp"; Description: "D Bindings"; Types: full -Name: "assimp_net"; Description: "C#/.NET Bindings"; Types: full [Run] ;Filename: "{app}\stub\vc_redist.x86.exe"; Parameters: "/qb"; StatusMsg: "Installing VS2017 redistributable package (32 Bit)"; Check: not IsWin64 Filename: "{app}\stub\vc_redist.x64.exe"; Parameters: "/qb"; StatusMsg: "Installing VS2017 redistributable package (64 Bit)"; Check: IsWin64 [Files] - Source: "readme_installer.txt"; DestDir: "{app}"; Flags: isreadme ; Installer stub @@ -55,15 +51,15 @@ Source: "WEB"; DestDir: "{app}" Source: "..\..\scripts\*"; DestDir: "{app}\scripts"; Flags: recursesubdirs ; x86 binaries -;Source: "..\..\bin\release\x86\assimp-vc140-mt.dll"; DestDir: "{app}\bin\x86" -;Source: "..\..\bin\release\x86\assimp_viewer.exe"; DestDir: "{app}\bin\x86"; Components: tools +;Source: "..\..\bin\release\x86\assimp-vc141-mt.dll"; DestDir: "{app}\bin\x86" +;Source: "..\..\bin\release\x86\assimp_viewer.exe"; DestDir: "{app}\bin\x86"; Components: tools ;Source: "D3DCompiler_42.dll"; DestDir: "{app}\bin\x86"; Components: tools ;Source: "D3DX9_42.dll"; DestDir: "{app}\bin\x86"; Components: tools ;Source: "..\..\bin\release\x86\assimp.exe"; DestDir: "{app}\bin\x86"; Components: tools ; x64 binaries -Source: "..\..\bin\release\assimp-vc140-mt.dll"; DestDir: "{app}\bin\x64" -Source: "..\..\bin\release\assimp_viewer.exe"; DestDir: "{app}\bin\x64"; Components: tools +Source: "..\..\bin\release\assimp-vc141-mt.dll"; DestDir: "{app}\bin\x64" +Source: "..\..\bin\release\assimp_viewer.exe"; DestDir: "{app}\bin\x64"; Components: tools Source: "D3DCompiler_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DCompiler_42.dll"; Components: tools Source: "D3DX9_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DX9_42.dll"; Components: tools Source: "..\..\bin\release\assimp.exe"; DestDir: "{app}\bin\x64"; Components: tools @@ -75,7 +71,7 @@ Source: "..\..\doc\datastructure.xml"; DestDir: "{app}\doc"; Components: help ; Import libraries ;Source: "..\..\lib\release\x86\assimp.lib"; DestDir: "{app}\lib\x86" -Source: "..\..\lib\release\assimp-vc140-mt.lib"; DestDir: "{app}\lib\x64" +Source: "..\..\lib\release\assimp-vc141-mt.lib"; DestDir: "{app}\lib\x64" ; Samples Source: "..\..\samples\*"; DestDir: "{app}\samples"; Flags: recursesubdirs; Components: samples From 24d49b0cc764e489dae5e9a4985c58cf683681a7 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 4 Jun 2018 09:01:17 +0200 Subject: [PATCH 256/278] Update appveyor.yml Add download request for the redistributables. --- appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index d574dafa6..aa2d8bc10 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -33,6 +33,8 @@ install: - if "%platform%"=="x64" set CMAKE_GENERATOR_NAME=%CMAKE_GENERATOR_NAME% Win64 - cmake %CMAKE_DEFINES% -G "%CMAKE_GENERATOR_NAME%" - set PATH=%PATH%;"C:\\Program Files (x86)\\Inno Setup 5" + - ps: Invoke-WebRequest -Uri https://download.microsoft.com/download/5/7/b/57b2947c-7221-4f33-b35e-2fc78cb10df4/vc_redist.x64.exe -OutFile .\packaging\windows-innosetup\vc_redist.x64.exe + - ps: Invoke-WebRequest -Uri https://download.microsoft.com/download/1/d/8/1d8137db-b5bb-4925-8c5d-927424a2e4de/vc_redist.x86.exe -OutFile .\packaging\windows-innosetup\vc_redist.x86.exe - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" iscc packaging\windows-innosetup\script.iss cache: From 20bfb3662f55decd0cc7b0186b9c65b7db26d60f Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 4 Jun 2018 11:53:44 +0200 Subject: [PATCH 257/278] Update script.iss FIx buggy names of dlls. --- packaging/windows-innosetup/script.iss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packaging/windows-innosetup/script.iss b/packaging/windows-innosetup/script.iss index 8debcb494..8364e51e2 100644 --- a/packaging/windows-innosetup/script.iss +++ b/packaging/windows-innosetup/script.iss @@ -51,14 +51,14 @@ Source: "WEB"; DestDir: "{app}" Source: "..\..\scripts\*"; DestDir: "{app}\scripts"; Flags: recursesubdirs ; x86 binaries -;Source: "..\..\bin\release\x86\assimp-vc141-mt.dll"; DestDir: "{app}\bin\x86" +;Source: "..\..\bin\release\x86\assimp-vc140-mt.dll"; DestDir: "{app}\bin\x86" ;Source: "..\..\bin\release\x86\assimp_viewer.exe"; DestDir: "{app}\bin\x86"; Components: tools ;Source: "D3DCompiler_42.dll"; DestDir: "{app}\bin\x86"; Components: tools ;Source: "D3DX9_42.dll"; DestDir: "{app}\bin\x86"; Components: tools ;Source: "..\..\bin\release\x86\assimp.exe"; DestDir: "{app}\bin\x86"; Components: tools ; x64 binaries -Source: "..\..\bin\release\assimp-vc141-mt.dll"; DestDir: "{app}\bin\x64" +Source: "..\..\bin\release\assimp-vc140-mt.dll"; DestDir: "{app}\bin\x64" Source: "..\..\bin\release\assimp_viewer.exe"; DestDir: "{app}\bin\x64"; Components: tools Source: "D3DCompiler_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DCompiler_42.dll"; Components: tools Source: "D3DX9_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DX9_42.dll"; Components: tools From 37ed614b70bc29a00d08dcb97a0ce79317458b1c Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 4 Jun 2018 15:02:37 +0200 Subject: [PATCH 258/278] Update appveyor.yml Run inno script after build. --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index aa2d8bc10..2b5f212f9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -35,7 +35,6 @@ install: - set PATH=%PATH%;"C:\\Program Files (x86)\\Inno Setup 5" - ps: Invoke-WebRequest -Uri https://download.microsoft.com/download/5/7/b/57b2947c-7221-4f33-b35e-2fc78cb10df4/vc_redist.x64.exe -OutFile .\packaging\windows-innosetup\vc_redist.x64.exe - ps: Invoke-WebRequest -Uri https://download.microsoft.com/download/1/d/8/1d8137db-b5bb-4925-8c5d-927424a2e4de/vc_redist.x86.exe -OutFile .\packaging\windows-innosetup\vc_redist.x86.exe - - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" iscc packaging\windows-innosetup\script.iss cache: - code\assimp.dir\%CONFIGURATION% @@ -54,6 +53,7 @@ build: project: Assimp.sln after_build: + - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" iscc packaging\windows-innosetup\script.iss - 7z a assimp.7z bin\%CONFIGURATION%\* lib\%CONFIGURATION%\* test_script: From c46008055c2f0a29126d64fffbc21f7cd60f93fc Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 4 Jun 2018 21:41:58 +0200 Subject: [PATCH 259/278] Update script.iss Directx: Use install path on appyevor image. --- packaging/windows-innosetup/script.iss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packaging/windows-innosetup/script.iss b/packaging/windows-innosetup/script.iss index 8364e51e2..471c3a53d 100644 --- a/packaging/windows-innosetup/script.iss +++ b/packaging/windows-innosetup/script.iss @@ -53,8 +53,8 @@ Source: "..\..\scripts\*"; DestDir: "{app}\scripts"; Flags: recursesubdirs ; x86 binaries ;Source: "..\..\bin\release\x86\assimp-vc140-mt.dll"; DestDir: "{app}\bin\x86" ;Source: "..\..\bin\release\x86\assimp_viewer.exe"; DestDir: "{app}\bin\x86"; Components: tools -;Source: "D3DCompiler_42.dll"; DestDir: "{app}\bin\x86"; Components: tools -;Source: "D3DX9_42.dll"; DestDir: "{app}\bin\x86"; Components: tools +;Source: "C:\Program Files (x86)\Microsoft DirectX SDK)\D3DCompiler_42.dll"; DestDir: "{app}\bin\x86"; Components: tools +;Source: "C:\Program Files (x86)\Microsoft DirectX SDK)\D3DX9_42.dll"; DestDir: "{app}\bin\x86"; Components: tools ;Source: "..\..\bin\release\x86\assimp.exe"; DestDir: "{app}\bin\x86"; Components: tools ; x64 binaries From ab301c1acc687945fc7bc6fa35dc991d4c3f8083 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 4 Jun 2018 22:08:20 +0200 Subject: [PATCH 260/278] Update script.iss - Fix x64-folders shwing to DirectX dlls - Remove dead code - Put doc copy ops for installer into brackets. --- packaging/windows-innosetup/script.iss | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/packaging/windows-innosetup/script.iss b/packaging/windows-innosetup/script.iss index 471c3a53d..33fadb57b 100644 --- a/packaging/windows-innosetup/script.iss +++ b/packaging/windows-innosetup/script.iss @@ -60,18 +60,18 @@ Source: "..\..\scripts\*"; DestDir: "{app}\scripts"; Flags: recursesubdirs ; x64 binaries Source: "..\..\bin\release\assimp-vc140-mt.dll"; DestDir: "{app}\bin\x64" Source: "..\..\bin\release\assimp_viewer.exe"; DestDir: "{app}\bin\x64"; Components: tools -Source: "D3DCompiler_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DCompiler_42.dll"; Components: tools -Source: "D3DX9_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DX9_42.dll"; Components: tools +Source: "C:\Program Files (x86)\Microsoft DirectX SDK)\D3DCompiler_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DCompiler_42.dll"; Components: tools +Source: "C:\Program Files (x86)\Microsoft DirectX SDK)\D3DX9_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DX9_42.dll"; Components: tools Source: "..\..\bin\release\assimp.exe"; DestDir: "{app}\bin\x64"; Components: tools ; Documentation -Source: "..\..\doc\AssimpDoc_Html\AssimpDoc.chm"; DestDir: "{app}\doc"; Components: help -Source: "..\..\doc\AssimpCmdDoc_Html\AssimpCmdDoc.chm"; DestDir: "{app}\doc"; Components: help -Source: "..\..\doc\datastructure.xml"; DestDir: "{app}\doc"; Components: help +;Source: "..\..\doc\AssimpDoc_Html\AssimpDoc.chm"; DestDir: "{app}\doc"; Components: help +;Source: "..\..\doc\AssimpCmdDoc_Html\AssimpCmdDoc.chm"; DestDir: "{app}\doc"; Components: help +:Source: "..\..\doc\datastructure.xml"; DestDir: "{app}\doc"; Components: help ; Import libraries ;Source: "..\..\lib\release\x86\assimp.lib"; DestDir: "{app}\lib\x86" -Source: "..\..\lib\release\assimp-vc141-mt.lib"; DestDir: "{app}\lib\x64" +Source: "..\..\lib\release\assimp-vc140-mt.lib"; DestDir: "{app}\lib\x64" ; Samples Source: "..\..\samples\*"; DestDir: "{app}\samples"; Flags: recursesubdirs; Components: samples @@ -93,15 +93,6 @@ Source: "..\..\port\dAssimp\*"; DestDir: "{app}\port\D"; Flags: recursesubdirs; ;Source: "..\..\test\regression\*"; DestDir: "{app}\test\regression"; Flags: recursesubdirs; Components: test ;Source: "..\..\test\models-nonbsd\*"; DestDir: "{app}\test\models-nonbsd"; Flags: recursesubdirs; Components: test_nonbsd -; Source Code & Workspaces -;Source: "..\..\code\*"; Excludes: "*.o"; DestDir: "{app}\code"; Flags: recursesubdirs; Components: wsource -;Source: "..\..\workspaces\vc8\*.sln"; DestDir: "{app}\workspaces\vc8"; Components: wsource and vc8 -;Source: "..\..\workspaces\vc8\*.vcproj"; DestDir: "{app}\workspaces\vc8"; Components: wsource and vc8 -;Source: "..\..\workspaces\vc9\*.sln"; DestDir: "{app}\workspaces\vc9"; Components: wsource and vc9 -;Source: "..\..\workspaces\vc9\*.vcproj"; DestDir: "{app}\workspaces\vc9"; Components: wsource and vc9 - -; Source: "Readme.txt"; DestDir: "{app}"; Flags: isreadme - [Icons] Name: "{group}\Assimp Manual"; Filename: "{app}\doc\AssimpDoc.chm" ; Components: help Name: "{group}\Assimp Command Line Manual"; Filename: "{app}\doc\AssimpCmdDoc.chm"; Components: help From 12438bcdb2ae185c5487bcc3496b4c2cefe5ad9a Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 4 Jun 2018 22:37:05 +0200 Subject: [PATCH 261/278] Update script.iss Typ fix --- packaging/windows-innosetup/script.iss | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packaging/windows-innosetup/script.iss b/packaging/windows-innosetup/script.iss index 33fadb57b..132054e88 100644 --- a/packaging/windows-innosetup/script.iss +++ b/packaging/windows-innosetup/script.iss @@ -53,15 +53,15 @@ Source: "..\..\scripts\*"; DestDir: "{app}\scripts"; Flags: recursesubdirs ; x86 binaries ;Source: "..\..\bin\release\x86\assimp-vc140-mt.dll"; DestDir: "{app}\bin\x86" ;Source: "..\..\bin\release\x86\assimp_viewer.exe"; DestDir: "{app}\bin\x86"; Components: tools -;Source: "C:\Program Files (x86)\Microsoft DirectX SDK)\D3DCompiler_42.dll"; DestDir: "{app}\bin\x86"; Components: tools -;Source: "C:\Program Files (x86)\Microsoft DirectX SDK)\D3DX9_42.dll"; DestDir: "{app}\bin\x86"; Components: tools +;Source: "C:\Program Files (x86)\Microsoft DirectX SDK\D3DCompiler_42.dll"; DestDir: "{app}\bin\x86"; Components: tools +;Source: "C:\Program Files (x86)\Microsoft DirectX SDK\D3DX9_42.dll"; DestDir: "{app}\bin\x86"; Components: tools ;Source: "..\..\bin\release\x86\assimp.exe"; DestDir: "{app}\bin\x86"; Components: tools ; x64 binaries Source: "..\..\bin\release\assimp-vc140-mt.dll"; DestDir: "{app}\bin\x64" Source: "..\..\bin\release\assimp_viewer.exe"; DestDir: "{app}\bin\x64"; Components: tools -Source: "C:\Program Files (x86)\Microsoft DirectX SDK)\D3DCompiler_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DCompiler_42.dll"; Components: tools -Source: "C:\Program Files (x86)\Microsoft DirectX SDK)\D3DX9_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DX9_42.dll"; Components: tools +Source: "C:\Program Files (x86)\Microsoft DirectX SDK\D3DCompiler_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DCompiler_42.dll"; Components: tools +Source: "C:\Program Files (x86)\Microsoft DirectX SDK\D3DX9_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DX9_42.dll"; Components: tools Source: "..\..\bin\release\assimp.exe"; DestDir: "{app}\bin\x64"; Components: tools ; Documentation From d55525d16b9f0f929c4689eaab899d32fec4324b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 5 Jun 2018 10:25:35 +0200 Subject: [PATCH 262/278] Update script.iss Fix folders to DX-dlls. --- packaging/windows-innosetup/script.iss | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packaging/windows-innosetup/script.iss b/packaging/windows-innosetup/script.iss index 132054e88..bed974f70 100644 --- a/packaging/windows-innosetup/script.iss +++ b/packaging/windows-innosetup/script.iss @@ -53,15 +53,15 @@ Source: "..\..\scripts\*"; DestDir: "{app}\scripts"; Flags: recursesubdirs ; x86 binaries ;Source: "..\..\bin\release\x86\assimp-vc140-mt.dll"; DestDir: "{app}\bin\x86" ;Source: "..\..\bin\release\x86\assimp_viewer.exe"; DestDir: "{app}\bin\x86"; Components: tools -;Source: "C:\Program Files (x86)\Microsoft DirectX SDK\D3DCompiler_42.dll"; DestDir: "{app}\bin\x86"; Components: tools -;Source: "C:\Program Files (x86)\Microsoft DirectX SDK\D3DX9_42.dll"; DestDir: "{app}\bin\x86"; Components: tools +;Source: "C:\Program Files (x86)\Microsoft DirectX SDK\Developer Runtime\x86\D3DCompiler_42.dll"; DestDir: "{app}\bin\x86"; Components: tools +;Source: "C:\Program Files (x86)\Microsoft DirectX SDK\Developer Runtime\x86\D3DX9_42.dll"; DestDir: "{app}\bin\x86"; Components: tools ;Source: "..\..\bin\release\x86\assimp.exe"; DestDir: "{app}\bin\x86"; Components: tools ; x64 binaries Source: "..\..\bin\release\assimp-vc140-mt.dll"; DestDir: "{app}\bin\x64" Source: "..\..\bin\release\assimp_viewer.exe"; DestDir: "{app}\bin\x64"; Components: tools -Source: "C:\Program Files (x86)\Microsoft DirectX SDK\D3DCompiler_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DCompiler_42.dll"; Components: tools -Source: "C:\Program Files (x86)\Microsoft DirectX SDK\D3DX9_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DX9_42.dll"; Components: tools +Source: "C:\Program Files (x86)\Microsoft DirectX SDK\Developer Runtime\x64\D3DCompiler_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DCompiler_42.dll"; Components: tools +Source: "C:\Program Files (x86)\Microsoft DirectX SDK\Developer Runtime\x64\D3DX9_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DX9_42.dll"; Components: tools Source: "..\..\bin\release\assimp.exe"; DestDir: "{app}\bin\x64"; Components: tools ; Documentation From c313d5a3e9ad56cf50a446ea2a06ee142fc30217 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 5 Jun 2018 10:55:51 +0200 Subject: [PATCH 263/278] Update script.iss Fix folders ... again --- packaging/windows-innosetup/script.iss | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packaging/windows-innosetup/script.iss b/packaging/windows-innosetup/script.iss index bed974f70..136b828c3 100644 --- a/packaging/windows-innosetup/script.iss +++ b/packaging/windows-innosetup/script.iss @@ -53,15 +53,15 @@ Source: "..\..\scripts\*"; DestDir: "{app}\scripts"; Flags: recursesubdirs ; x86 binaries ;Source: "..\..\bin\release\x86\assimp-vc140-mt.dll"; DestDir: "{app}\bin\x86" ;Source: "..\..\bin\release\x86\assimp_viewer.exe"; DestDir: "{app}\bin\x86"; Components: tools -;Source: "C:\Program Files (x86)\Microsoft DirectX SDK\Developer Runtime\x86\D3DCompiler_42.dll"; DestDir: "{app}\bin\x86"; Components: tools -;Source: "C:\Program Files (x86)\Microsoft DirectX SDK\Developer Runtime\x86\D3DX9_42.dll"; DestDir: "{app}\bin\x86"; Components: tools +;Source: "C:\Windows\SysWOW64\D3DCompiler_42.dll"; DestDir: "{app}\bin\x86"; Components: tools +;Source: "C:\Windows\SysWOW64\D3DX9_42.dll"; DestDir: "{app}\bin\x86"; Components: tools ;Source: "..\..\bin\release\x86\assimp.exe"; DestDir: "{app}\bin\x86"; Components: tools ; x64 binaries Source: "..\..\bin\release\assimp-vc140-mt.dll"; DestDir: "{app}\bin\x64" Source: "..\..\bin\release\assimp_viewer.exe"; DestDir: "{app}\bin\x64"; Components: tools -Source: "C:\Program Files (x86)\Microsoft DirectX SDK\Developer Runtime\x64\D3DCompiler_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DCompiler_42.dll"; Components: tools -Source: "C:\Program Files (x86)\Microsoft DirectX SDK\Developer Runtime\x64\D3DX9_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DX9_42.dll"; Components: tools +Source: "C:\Windows\SysWOW64\D3DCompiler_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DCompiler_42.dll"; Components: tools +Source: "C:\Windows\SysWOW64\D3DX9_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DX9_42.dll"; Components: tools Source: "..\..\bin\release\assimp.exe"; DestDir: "{app}\bin\x64"; Components: tools ; Documentation From de088328aad6b9397989b49537790f3df0f93d17 Mon Sep 17 00:00:00 2001 From: kimkulling Date: Tue, 5 Jun 2018 11:27:24 +0200 Subject: [PATCH 264/278] replace typo by comment statement. --- packaging/windows-innosetup/script.iss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/windows-innosetup/script.iss b/packaging/windows-innosetup/script.iss index 136b828c3..6c4b9cd37 100644 --- a/packaging/windows-innosetup/script.iss +++ b/packaging/windows-innosetup/script.iss @@ -67,7 +67,7 @@ Source: "..\..\bin\release\assimp.exe"; DestDir: "{app}\bin\x64"; Comp ; Documentation ;Source: "..\..\doc\AssimpDoc_Html\AssimpDoc.chm"; DestDir: "{app}\doc"; Components: help ;Source: "..\..\doc\AssimpCmdDoc_Html\AssimpCmdDoc.chm"; DestDir: "{app}\doc"; Components: help -:Source: "..\..\doc\datastructure.xml"; DestDir: "{app}\doc"; Components: help +;Source: "..\..\doc\datastructure.xml"; DestDir: "{app}\doc"; Components: help ; Import libraries ;Source: "..\..\lib\release\x86\assimp.lib"; DestDir: "{app}\lib\x86" From e07aedac9e24eb8164043ab56da7b044b0ca1b0a Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 6 Jun 2018 10:39:17 +0200 Subject: [PATCH 265/278] Update script.iss add missing components andput the into brackets. --- packaging/windows-innosetup/script.iss | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packaging/windows-innosetup/script.iss b/packaging/windows-innosetup/script.iss index 6c4b9cd37..695740679 100644 --- a/packaging/windows-innosetup/script.iss +++ b/packaging/windows-innosetup/script.iss @@ -30,6 +30,9 @@ Name: "help"; Description: "Help Files"; Types: full compact Name: "samples"; Description: "Samples"; Types: full Name: "test"; Description: "Test Models (BSD-licensed)"; Types: full Name: "test_nonbsd"; Description: "Test Models (other (free) licenses)"; Types: full +;Name: "pyassimp"; Description: "Python Bindings"; Types: full +;Name: "dassimp"; Description: "D Bindings"; Types: full +;Name: "assimp_net"; Description: "C#/.NET Bindings"; Types: full [Run] ;Filename: "{app}\stub\vc_redist.x86.exe"; Parameters: "/qb"; StatusMsg: "Installing VS2017 redistributable package (32 Bit)"; Check: not IsWin64 @@ -80,7 +83,7 @@ Source: "..\..\samples\*"; DestDir: "{app}\samples"; Flags: recursesubdirs; Comp Source: "..\..\include\*"; DestDir: "{app}\include"; Flags: recursesubdirs ; dAssimp -Source: "..\..\port\dAssimp\*"; DestDir: "{app}\port\D"; Flags: recursesubdirs; Components: dassimp +;Source: "..\..\port\dAssimp\*"; DestDir: "{app}\port\D"; Flags: recursesubdirs; Components: dassimp ; Assimp.NET ;Source: "..\..\port\Assimp.NET\*"; DestDir: "{app}\port\C#"; Flags: recursesubdirs; Components: assimp_net From 85b0026c922460dac3ccf39f2a5e8b3d175ac6cc Mon Sep 17 00:00:00 2001 From: CwTCwT Date: Sat, 9 Jun 2018 15:45:09 +0200 Subject: [PATCH 266/278] issue_1973 added support for CustomData(Layer) to support multiple (texture) UV mappings added unittest with sample model --- code/BlenderCustomData.cpp | 212 ++++++++++++++++++ code/BlenderCustomData.h | 101 +++++++++ code/BlenderDNA.h | 22 ++ code/BlenderDNA.inl | 118 ++++++++++ code/BlenderLoader.cpp | 78 ++++++- code/BlenderScene.cpp | 45 ++++ code/BlenderScene.h | 83 ++++++- code/BlenderSceneGen.h | 11 + code/CMakeLists.txt | 2 + code/STLLoader.cpp | 25 ++- .../plane_2_textures_2_texcoords_279.blend | Bin 0 -> 512624 bytes test/unit/utBlendImportMaterials.cpp | 27 +++ 12 files changed, 707 insertions(+), 17 deletions(-) create mode 100644 code/BlenderCustomData.cpp create mode 100644 code/BlenderCustomData.h create mode 100644 test/models/BLEND/plane_2_textures_2_texcoords_279.blend diff --git a/code/BlenderCustomData.cpp b/code/BlenderCustomData.cpp new file mode 100644 index 000000000..7f518b782 --- /dev/null +++ b/code/BlenderCustomData.cpp @@ -0,0 +1,212 @@ +#pragma once + +#include "BlenderCustomData.h" +#include + +namespace Assimp { + namespace Blender + { + /** + * @brief read/convert of Structure array to memory + */ + template + bool read(const Structure &s, T *p, const size_t cnt, const FileDatabase &db) { + for (size_t i = 0; i < cnt; ++i) { + T read; + s.Convert(read, db); + *p = read; + p++; + } + return true; + } + + /** + * @brief pointer to function read memory for n CustomData types + */ + typedef bool(*PRead)(void *pOut, const size_t cnt, const FileDatabase &db); + /** + * @brief pointer to function read memory for cnt CustomData types + */ + typedef void *(*PAlloc)(const size_t cnt); + + /** + * @brief helper macro to define Structure specific read function + * for ex: when used like + * + * IMPL_STRUCT_READ(MLoop) + * + * following function is implemented + * + * bool readMLoop(void *v, const size_t cnt, const FileDatabase &db) { + * return read(db.dna["MLoop"], static_cast(v), cnt, db); + * } + */ +#define IMPL_STRUCT_READ(ty) \ + bool read##ty(void *v, const size_t cnt, const FileDatabase &db) { \ + return read(db.dna[#ty], static_cast(v), cnt, db); \ + } + + /** + * @brief helper macro to define Structure specific alloc function + * for ex: when used like + * + * IMPL_STRUCT_ALLOC(MLoop) + * + * following function is implemented + * + * void * allocMLoop(const size_t cnt) { + * return new uint8_t[cnt * sizeof MLoop]; + * } + */ +#define IMPL_STRUCT_ALLOC(ty) \ + void *alloc##ty(const size_t cnt) { \ + return new uint8_t[cnt * sizeof ty]; \ + } + + /** + * @brief helper macro to define Structure functions + */ +#define IMPL_STRUCT(ty) \ + IMPL_STRUCT_ALLOC(ty) \ + IMPL_STRUCT_READ(ty) + + // supported structures for CustomData + IMPL_STRUCT(MVert) + IMPL_STRUCT(MEdge) + IMPL_STRUCT(MFace) + IMPL_STRUCT(MTFace) + IMPL_STRUCT(MTexPoly) + IMPL_STRUCT(MLoopUV) + IMPL_STRUCT(MLoopCol) + IMPL_STRUCT(MPoly) + IMPL_STRUCT(MLoop) + + /** + * @brief describes the size of data and the read function to be used for single CustomerData.type + */ + struct CustomDataTypeDescription + { + PRead Read; ///< function to read one CustomData type element + PAlloc Alloc; ///< function to allocate n type elements + }; + + /** + * @brief shortcut for array of CustomDataTypeDescription + */ + typedef std::array CustomDataTypeDescriptions; + + /** + * @brief helper macro to define Structure type specific CustomDataTypeDescription + * @note IMPL_STRUCT_READ for same ty must be used earlier to implement the typespecific read function + */ +#define DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(ty) \ + CustomDataTypeDescription{ &read##ty, &alloc##ty } + + /** + * @brief helper macro to define CustomDataTypeDescription for UNSUPPORTED type + */ +#define DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION \ + CustomDataTypeDescription{ nullptr, nullptr } + + /** + * @brief descriptors for data pointed to from CustomDataLayer.data + * @note some of the CustomData uses already well defined Structures + * other (like CD_ORCO, ...) uses arrays of rawtypes or even arrays of Structures + * use a special readfunction for that cases + */ + CustomDataTypeDescriptions customDataTypeDescriptions = + { + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MVert), + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MEdge), + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MFace), + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MTFace), + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MTexPoly), + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopUV), + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopCol), + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MPoly), + DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoop), + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION, + DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION + }; + + + bool isValidCustomDataType(const int cdtype) + { + return cdtype >= 0 && cdtype < CD_NUMTYPES; + } + + bool readCustomData(std::shared_ptr &out, const CustomDataType cdtype, const size_t cnt, const FileDatabase &db) + { + if (!isValidCustomDataType(cdtype)) + { + throw Error((Formatter::format(), "CustomData.type ", cdtype, " out of index")); + } + + const CustomDataTypeDescription cdtd = customDataTypeDescriptions[cdtype]; + if (cdtd.Read && cdtd.Alloc) + { + // allocate cnt elements and parse them from file + out.reset(cdtd.Alloc(cnt)); + return cdtd.Read(out.get(), cnt, db); + } + return false; + } + + std::shared_ptr getCustomDataLayer(const CustomData &customdata, const CustomDataType cdtype, const std::string &name) + { + for (auto it = customdata.layers.begin(); it != customdata.layers.end(); ++it) + { + if (it->get()->type == cdtype && name == it->get()->name) + { + return *it; + } + } + return nullptr; + } + + const void * getCustomDataLayerData(const CustomData &customdata, const CustomDataType cdtype, const std::string &name) + { + const std::shared_ptr pLayer = getCustomDataLayer(customdata, cdtype, name); + if (pLayer && pLayer->data) + { + return pLayer->data.get(); + } + return nullptr; + } + } +} diff --git a/code/BlenderCustomData.h b/code/BlenderCustomData.h new file mode 100644 index 000000000..b6f3641f1 --- /dev/null +++ b/code/BlenderCustomData.h @@ -0,0 +1,101 @@ +#pragma once + +#include "BlenderDNA.h" +#include "BlenderScene.h" +#include + +namespace Assimp { + namespace Blender + { + /* CustomData.type from Blender (2.79b) */ + enum CustomDataType + { + CD_AUTO_FROM_NAME = -1, + CD_MVERT = 0, +#ifdef DNA_DEPRECATED + CD_MSTICKY = 1, /* DEPRECATED */ +#endif + CD_MDEFORMVERT = 2, + CD_MEDGE = 3, + CD_MFACE = 4, + CD_MTFACE = 5, + CD_MCOL = 6, + CD_ORIGINDEX = 7, + CD_NORMAL = 8, + /* CD_POLYINDEX = 9, */ + CD_PROP_FLT = 10, + CD_PROP_INT = 11, + CD_PROP_STR = 12, + CD_ORIGSPACE = 13, /* for modifier stack face location mapping */ + CD_ORCO = 14, + CD_MTEXPOLY = 15, + CD_MLOOPUV = 16, + CD_MLOOPCOL = 17, + CD_TANGENT = 18, + CD_MDISPS = 19, + CD_PREVIEW_MCOL = 20, /* for displaying weightpaint colors */ + /* CD_ID_MCOL = 21, */ + CD_TEXTURE_MLOOPCOL = 22, + CD_CLOTH_ORCO = 23, + CD_RECAST = 24, + + /* BMESH ONLY START */ + CD_MPOLY = 25, + CD_MLOOP = 26, + CD_SHAPE_KEYINDEX = 27, + CD_SHAPEKEY = 28, + CD_BWEIGHT = 29, + CD_CREASE = 30, + CD_ORIGSPACE_MLOOP = 31, + CD_PREVIEW_MLOOPCOL = 32, + CD_BM_ELEM_PYPTR = 33, + /* BMESH ONLY END */ + + CD_PAINT_MASK = 34, + CD_GRID_PAINT_MASK = 35, + CD_MVERT_SKIN = 36, + CD_FREESTYLE_EDGE = 37, + CD_FREESTYLE_FACE = 38, + CD_MLOOPTANGENT = 39, + CD_TESSLOOPNORMAL = 40, + CD_CUSTOMLOOPNORMAL = 41, + + CD_NUMTYPES = 42 + }; + + /** + * @brief check if given cdtype is valid (ie >= 0 and < CD_NUMTYPES) + * @param[in] cdtype to check + * @return true when valid + */ + bool isValidCustomDataType(const int cdtype); + + /** + * @brief read CustomData's data to ptr to mem + * @param[out] out memory ptr to set + * @param[in] cdtype to read + * @param[in] cnt cnt of elements to read + * @param[in] db to read elements from + * @return true when ok + */ + bool readCustomData(std::shared_ptr &out, CustomDataType cdtype, size_t cnt, const FileDatabase &db); + + /** + * @brief returns CustomDataLayer ptr for given cdtype and name + * @param[in] customdata CustomData to search for wanted layer + * @param[in] cdtype to search for + * @param[in] name to search for + * @return CustomDataLayer * or nullptr if not found + */ + std::shared_ptr getCustomDataLayer(const CustomData &customdata, CustomDataType cdtype, const std::string &name); + + /** + * @brief returns CustomDataLayer data ptr for given cdtype and name + * @param[in] customdata CustomData to search for wanted layer + * @param[in] cdtype to search for + * @param[in] name to search for + * @return CustomDataLayer * or nullptr if not found + */ + const void * getCustomDataLayerData(const CustomData &customdata, CustomDataType cdtype, const std::string &name); + } +} diff --git a/code/BlenderDNA.h b/code/BlenderDNA.h index 6a18fe9fa..d2b897d3a 100644 --- a/code/BlenderDNA.h +++ b/code/BlenderDNA.h @@ -309,6 +309,28 @@ public: void ReadField(T& out, const char* name, const FileDatabase& db) const; + // -------------------------------------------------------- + /** + * @brief field parsing for dynamic vectors + * @param[in] out vector of struct to be filled + * @param[in] name of field + * @param[in] db to access the file, dna, ... + * @return true when read was successful + */ + template class TOUT, typename T> + bool ReadFieldPtrVector(vector>&out, const char* name, const FileDatabase& db) const; + + /** + * @brief parses raw customdata + * @param[in] out shared_ptr to be filled + * @param[in] cdtype customdata type to read + * @param[in] name of field ptr + * @param[in] db to access the file, dna, ... + * @return true when read was successful + */ + template + bool ReadCustomDataPtr(std::shared_ptr&out, int cdtype, const char* name, const FileDatabase& db) const; + private: // -------------------------------------------------------- diff --git a/code/BlenderDNA.inl b/code/BlenderDNA.inl index e43d15d38..ae48a5896 100644 --- a/code/BlenderDNA.inl +++ b/code/BlenderDNA.inl @@ -307,6 +307,124 @@ void Structure :: ReadField(T& out, const char* name, const FileDatabase& db) co } +//-------------------------------------------------------------------------------- +// field parsing for raw untyped data (like CustomDataLayer.data) +template +bool Structure::ReadCustomDataPtr(std::shared_ptr&out, int cdtype, const char* name, const FileDatabase& db) const +{ + if (!isValidCustomDataType(cdtype)) + { + ASSIMP_LOG_ERROR("given rawtype out of index"); + return false; + } + + const StreamReaderAny::pos old = db.reader->GetCurrentPos(); + + Pointer ptrval; + const Field* f; + try + { + f = &(*this)[name]; + + // sanity check, should never happen if the genblenddna script is right + if (!(f->flags & FieldFlag_Pointer)) + { + throw Error((Formatter::format(), "Field `", name, "` of structure `", + this->name, "` ought to be a pointer")); + } + + db.reader->IncPtr(f->offset); + Convert(ptrval, db); + // actually it is meaningless on which Structure the Convert is called + // because the `Pointer` argument triggers a special implementation. + } + catch (const Error& e) + { + _defaultInitializer()(out, e.what()); + out.reset(); + } + + bool readOk = true; + if (ptrval.val) + { + // get block for ptr + const FileBlockHead* block = LocateFileBlockForAddress(ptrval, db); + db.reader->SetCurrentPos(block->start + static_cast((ptrval.val - block->address.val))); + // read block->num instances of given type to out + readOk = readCustomData(out, static_cast(cdtype), block->num, db); + } + + // and recover the previous stream position + db.reader->SetCurrentPos(old); + +#ifndef ASSIMP_BUILD_BLENDER_NO_STATS + ++db.stats().fields_read; +#endif + + return readOk; +} + +//-------------------------------------------------------------------------------- +template class TOUT, typename T> +bool Structure::ReadFieldPtrVector(vector>&out, const char* name, const FileDatabase& db) const +{ + out.clear(); + + const StreamReaderAny::pos old = db.reader->GetCurrentPos(); + + Pointer ptrval; + const Field* f; + try + { + f = &(*this)[name]; + + // sanity check, should never happen if the genblenddna script is right + if (!(f->flags & FieldFlag_Pointer)) + { + throw Error((Formatter::format(), "Field `", name, "` of structure `", + this->name, "` ought to be a pointer")); + } + + db.reader->IncPtr(f->offset); + Convert(ptrval, db); + // actually it is meaningless on which Structure the Convert is called + // because the `Pointer` argument triggers a special implementation. + } + catch (const Error& e) + { + _defaultInitializer()(out, e.what()); + out.clear(); + return false; + } + + + if (ptrval.val) + { + // find the file block the pointer is pointing to + const FileBlockHead* block = LocateFileBlockForAddress(ptrval, db); + db.reader->SetCurrentPos(block->start + static_cast((ptrval.val - block->address.val))); + // FIXME: basically, this could cause problems with 64 bit pointers on 32 bit systems. + // I really ought to improve StreamReader to work with 64 bit indices exclusively. + + const Structure& s = db.dna[f->type]; + for (size_t i = 0; i < block->num; ++i) + { + TOUT p(new T); + s.Convert(*p, db); + out.push_back(p); + } + } + + db.reader->SetCurrentPos(old); + +#ifndef ASSIMP_BUILD_BLENDER_NO_STATS + ++db.stats().fields_read; +#endif + + return false; +} + + //-------------------------------------------------------------------------------- template