From e9b67cdb89b07ac14d193eb058280df824a26377 Mon Sep 17 00:00:00 2001 From: Yingying Wang Date: Mon, 11 May 2020 14:34:35 -0700 Subject: [PATCH 01/21] gltf2 import sparse accessor --- code/AssetLib/glTF2/glTF2Asset.h | 18 ++++++ code/AssetLib/glTF2/glTF2Asset.inl | 93 +++++++++++++++++++++++++++++- 2 files changed, 109 insertions(+), 2 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index 48dab24a7..bae4c4eca 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -367,6 +367,7 @@ struct Object { //! An accessor provides a typed view into a BufferView or a subset of a BufferView //! similar to how WebGL's vertexAttribPointer() defines an attribute in a buffer. struct Accessor : public Object { + struct Sparse; Ref bufferView; //!< The ID of the bufferView. (required) size_t byteOffset; //!< The offset relative to the start of the bufferView in bytes. (required) ComponentType componentType; //!< The datatype of components in the attribute. (required) @@ -374,6 +375,7 @@ struct Accessor : public Object { AttribType::Value type; //!< Specifies if the attribute is a scalar, vector, or matrix. (required) std::vector max; //!< Maximum value of each component in this attribute. std::vector min; //!< Minimum value of each component in this attribute. + std::unique_ptr sparse; unsigned int GetNumComponents(); unsigned int GetBytesPerComponent(); @@ -423,6 +425,21 @@ struct Accessor : public Object { Accessor() {} void Read(Value &obj, Asset &r); + + //sparse + struct Sparse { + size_t count; + ComponentType indicesType; + Ref indices; + size_t indicesByteOffset; + Ref values; + size_t valuesByteOffset; + + std::vector data; //!< Actual data, which may be defaulted to an array of zeros or the original data, with the sparse buffer view applied on top of it. + + void PopulateData(size_t numBytes, uint8_t *bytes); + void PatchData(unsigned int elementSize); + }; }; //! A buffer points to binary geometry, animation, or skins. @@ -555,6 +572,7 @@ struct BufferView : public Object { BufferViewTarget target; //! The target that the WebGL buffer should be bound to. void Read(Value &obj, Asset &r); + uint8_t *GetPointer(size_t accOffset); }; struct Camera : public Object { diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index 881fd4efc..428001e6b 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -550,9 +550,62 @@ inline void BufferView::Read(Value &obj, Asset &r) { byteStride = MemberOrDefault(obj, "byteStride", 0u); } +inline uint8_t *BufferView::GetPointer(size_t accOffset) { + if (!buffer) return 0; + uint8_t *basePtr = buffer->GetPointer(); + if (!basePtr) return 0; + + size_t offset = accOffset + byteOffset; + if (buffer->EncodedRegion_Current != nullptr) { + const size_t begin = buffer->EncodedRegion_Current->Offset; + const size_t end = begin + buffer->EncodedRegion_Current->DecodedData_Length; + if ((offset >= begin) && (offset < end)) + return &buffer->EncodedRegion_Current->DecodedData[offset - begin]; + } + + return basePtr + offset; +} // // struct Accessor // +inline void Accessor::Sparse::PopulateData(size_t numBytes, uint8_t *bytes) { + if (bytes) { + data.assign(bytes, bytes + numBytes); + } else { + data.resize(numBytes, 0x00); + } +} + +inline void Accessor::Sparse::PatchData(unsigned int elementSize) { + uint8_t *pIndices = indices->GetPointer(indicesByteOffset); + const unsigned int indexSize = int(ComponentTypeSize(indicesType)); + uint8_t *indicesEnd = pIndices + count * indexSize; + + uint8_t *pValues = values->GetPointer(valuesByteOffset); + while (pIndices != indicesEnd) { + size_t offset; + switch (indicesType) { + case ComponentType_UNSIGNED_BYTE: + offset = *pIndices; + break; + case ComponentType_UNSIGNED_SHORT: + offset = *reinterpret_cast(pIndices); + break; + case ComponentType_UNSIGNED_INT: + offset = *reinterpret_cast(pIndices); + break; + default: + // have fun with float and negative values from signed types as indices. + throw DeadlyImportError("Unsupported component type in index."); + } + + offset *= elementSize; + std::memcpy(data.data() + offset, pValues, elementSize); + + pValues += elementSize; + pIndices += indexSize; + } +} inline void Accessor::Read(Value &obj, Asset &r) { @@ -566,6 +619,40 @@ inline void Accessor::Read(Value &obj, Asset &r) { const char *typestr; type = ReadMember(obj, "type", typestr) ? AttribType::FromString(typestr) : AttribType::SCALAR; + + if (Value *sparseValue = FindObject(obj, "sparse")) { + sparse.reset(new Sparse); + // count + ReadMember(*sparseValue, "count", sparse->count); + + // indices + if (Value *indicesValue = FindObject(*sparseValue, "indices")) { + //indices bufferView + Value *indiceViewID = FindUInt(*indicesValue, "bufferView"); + sparse->indices = r.bufferViews.Retrieve(indiceViewID->GetUint()); + //indices byteOffset + sparse->indicesByteOffset = MemberOrDefault(*indicesValue, "byteOffset", size_t(0)); + //indices componentType + sparse->indicesType = MemberOrDefault(*indicesValue, "componentType", ComponentType_BYTE); + } + + // value + if (Value *valuesValue = FindObject(*sparseValue, "values")) { + //value bufferView + Value *valueViewID = FindUInt(*valuesValue, "bufferView"); + sparse->values = r.bufferViews.Retrieve(valueViewID->GetUint()); + //value byteOffset + sparse->valuesByteOffset = MemberOrDefault(*valuesValue, "byteOffset", size_t(0)); + } + + // indicesType + sparse->indicesType = MemberOrDefault(*sparseValue, "componentType", ComponentType_UNSIGNED_SHORT); + + const unsigned int elementSize = GetElementSize(); + const size_t dataSize = count * elementSize; + sparse->PopulateData(dataSize, bufferView ? bufferView->GetPointer(byteOffset) : 0); + sparse->PatchData(elementSize); + } } inline unsigned int Accessor::GetNumComponents() { @@ -581,6 +668,9 @@ inline unsigned int Accessor::GetElementSize() { } inline uint8_t *Accessor::GetPointer() { + if (sparse) + return sparse->data.data(); + if (!bufferView || !bufferView->buffer) return 0; uint8_t *basePtr = bufferView->buffer->GetPointer(); if (!basePtr) return 0; @@ -634,8 +724,7 @@ void Accessor::ExtractData(T *&outData) const size_t targetElemSize = sizeof(T); ai_assert(elemSize <= targetElemSize); - - ai_assert(count * stride <= bufferView->byteLength); + ai_assert(count * stride <= (bufferView ? bufferView->byteLength : sparse->data.size())); outData = new T[count]; if (stride == elemSize && targetElemSize == elemSize) { From 7a16a7a7e4b78be8d3887c1288831488edff83f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Kangasj=C3=A4rvel=C3=A4?= Date: Fri, 15 May 2020 16:48:41 +0300 Subject: [PATCH 02/21] Fix infinite recursion in gltf2 skin parsing Previously parsing a node caused the skin that was attached to it to be parsed, which caused the skins node joints to be parsed, which could cause the skin to be re-parsed leading to infinite or at the very least exponential recursion. The fix is to just get a reference to a temporarily uninitialized skin as they were being parsed after the scene graph just to be safe anyway. This way we avoid the recursion problem and all the references will be valid in the end. --- code/AssetLib/glTF2/glTF2Asset.inl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index 5e1cc42d6..e3fff61a7 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -1188,9 +1188,11 @@ inline void Node::Read(Value &obj, Asset &r) { } } + // Do not retrieve a skin here, just take a reference, to avoid infinite recursion + // Skins will be properly loaded later Value *curSkin = FindUInt(obj, "skin"); if (nullptr != curSkin) { - this->skin = r.skins.Retrieve(curSkin->GetUint()); + this->skin = r.skins.Get(curSkin->GetUint()); } Value *curCamera = FindUInt(obj, "camera"); @@ -1481,7 +1483,7 @@ inline void Asset::Load(const std::string &pFile, bool isBinary) { } } - // Force reading of skins since they're not always directly referenced + // Read skins after nodes have been loaded to avoid infinite recursion if (Value *skinsArray = FindArray(doc, "skins")) { for (unsigned int i = 0; i < skinsArray->Size(); ++i) { skins.Retrieve(i); From 6be0ce1ec93a373a1c0f8cf3ab1499e906560fb1 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Thu, 14 May 2020 17:43:31 +0100 Subject: [PATCH 03/21] Initial pass at adding logging --- code/AssetLib/FBX/FBXBinaryTokenizer.cpp | 5 ++- code/AssetLib/FBX/FBXCompileConfig.h | 6 +++ code/AssetLib/FBX/FBXConverter.h | 2 +- code/AssetLib/FBX/FBXDocument.cpp | 5 +++ code/AssetLib/FBX/FBXImporter.cpp | 2 + code/AssetLib/FBX/FBXParser.cpp | 2 + code/AssetLib/FBX/FBXTokenizer.cpp | 4 +- code/AssetLib/glTF2/glTF2Importer.cpp | 33 +++++++++++---- include/assimp/Logger.hpp | 52 ++++++++++++------------ 9 files changed, 72 insertions(+), 39 deletions(-) diff --git a/code/AssetLib/FBX/FBXBinaryTokenizer.cpp b/code/AssetLib/FBX/FBXBinaryTokenizer.cpp index 7faa0518b..dd84196f1 100644 --- a/code/AssetLib/FBX/FBXBinaryTokenizer.cpp +++ b/code/AssetLib/FBX/FBXBinaryTokenizer.cpp @@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include namespace Assimp { namespace FBX { @@ -426,7 +427,8 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, // TODO: Test FBX Binary files newer than the 7500 version to check if the 64 bits address behaviour is consistent void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length) { - ai_assert(input); + ai_assert(input); + ASSIMP_FBX_LOG_DEBUG("Tokenizing binary FBX file"); if(length < 0x1b) { TokenizeError("file is too short",0); @@ -451,6 +453,7 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length) /*Result ignored*/ ReadByte(input, cursor, input + length); /*Result ignored*/ ReadByte(input, cursor, input + length); const uint32_t version = ReadWord(input, cursor, input + length); + ASSIMP_FBX_LOG_DEBUG_F("FBX version: ", version); const bool is64bits = version >= 7500; const char *end = input + length; while (cursor < end ) { diff --git a/code/AssetLib/FBX/FBXCompileConfig.h b/code/AssetLib/FBX/FBXCompileConfig.h index 5cdaa6960..31c8a5fdd 100644 --- a/code/AssetLib/FBX/FBXCompileConfig.h +++ b/code/AssetLib/FBX/FBXCompileConfig.h @@ -75,4 +75,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # endif #endif +#ifndef ASSIMP_FBX_LOG_DEBUG +// These require the DefaultLogger header. +#define ASSIMP_FBX_LOG_DEBUG ASSIMP_LOG_DEBUG +#define ASSIMP_FBX_LOG_DEBUG_F ASSIMP_LOG_DEBUG_F +#endif + #endif // INCLUDED_AI_FBX_COMPILECONFIG_H diff --git a/code/AssetLib/FBX/FBXConverter.h b/code/AssetLib/FBX/FBXConverter.h index d4f75820f..c24434c34 100644 --- a/code/AssetLib/FBX/FBXConverter.h +++ b/code/AssetLib/FBX/FBXConverter.h @@ -412,7 +412,7 @@ private: // ------------------------------------------------------------------------------------------------ // FBX file could have embedded textures not connected to anything - void ConvertOrphantEmbeddedTextures(); + void ConvertOrphanedEmbeddedTextures(); private: // 0: not assigned yet, others: index is value - 1 diff --git a/code/AssetLib/FBX/FBXDocument.cpp b/code/AssetLib/FBX/FBXDocument.cpp index 5940f3cfa..063ad677c 100644 --- a/code/AssetLib/FBX/FBXDocument.cpp +++ b/code/AssetLib/FBX/FBXDocument.cpp @@ -55,6 +55,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXDocumentUtil.h" #include "FBXProperties.h" +#include + #include #include #include @@ -264,6 +266,8 @@ Document::Document(const Parser& parser, const ImportSettings& settings) : settings(settings) , parser(parser) { + ASSIMP_FBX_LOG_DEBUG("Creating FBX Document"); + // Cannot use array default initialization syntax because vc8 fails on it for (auto &timeStamp : creationTimeStamp) { timeStamp = 0; @@ -308,6 +312,7 @@ void Document::ReadHeader() { const Scope& shead = *ehead->Compound(); fbxVersion = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(shead,"FBXVersion",ehead),0)); + ASSIMP_FBX_LOG_DEBUG_F("FBX Version: ", fbxVersion); // While we may have some success with newer files, we don't support // the older 6.n fbx format diff --git a/code/AssetLib/FBX/FBXImporter.cpp b/code/AssetLib/FBX/FBXImporter.cpp index 11c1503d8..232f78c13 100644 --- a/code/AssetLib/FBX/FBXImporter.cpp +++ b/code/AssetLib/FBX/FBXImporter.cpp @@ -146,6 +146,8 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy ThrowException("Could not open file for reading"); } + ASSIMP_FBX_LOG_DEBUG("Reading FBX file"); + // read entire file into memory - no streaming for this, fbx // files can grow large, but the assimp output data structure // then becomes very large, too. Assimp doesn't support diff --git a/code/AssetLib/FBX/FBXParser.cpp b/code/AssetLib/FBX/FBXParser.cpp index aef59d60c..04c58f70c 100644 --- a/code/AssetLib/FBX/FBXParser.cpp +++ b/code/AssetLib/FBX/FBXParser.cpp @@ -59,6 +59,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include @@ -220,6 +221,7 @@ Parser::Parser (const TokenList& tokens, bool is_binary) , cursor(tokens.begin()) , is_binary(is_binary) { + ASSIMP_FBX_LOG_DEBUG("Parsing FBX tokens"); root.reset(new Scope(*this,true)); } diff --git a/code/AssetLib/FBX/FBXTokenizer.cpp b/code/AssetLib/FBX/FBXTokenizer.cpp index 831c40061..1fe39a175 100644 --- a/code/AssetLib/FBX/FBXTokenizer.cpp +++ b/code/AssetLib/FBX/FBXTokenizer.cpp @@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXTokenizer.h" #include "FBXUtil.h" #include +#include namespace Assimp { namespace FBX { @@ -134,7 +135,8 @@ void ProcessDataToken( TokenList& output_tokens, const char*& start, const char* // ------------------------------------------------------------------------------------------------ void Tokenize(TokenList& output_tokens, const char* input) { - ai_assert(input); + ai_assert(input); + ASSIMP_FBX_LOG_DEBUG("Tokenizing ascii FBX file"); // line and column numbers numbers are one-based unsigned int line = 1; diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index 10d0bc83b..ee6a1b298 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -286,6 +286,7 @@ static aiMaterial *ImportMaterial(std::vector &embeddedTexIdxs, Asset &r, M void glTF2Importer::ImportMaterials(glTF2::Asset &r) { const unsigned int numImportedMaterials = unsigned(r.materials.Size()); + ASSIMP_GLTF_LOG_DEBUG_F("Importing ", numImportedMaterials, " materials"); Material defaultMaterial; mScene->mNumMaterials = numImportedMaterials + 1; @@ -333,6 +334,7 @@ static inline bool CheckValidFacesIndices(aiFace *faces, unsigned nFaces, unsign #endif // ASSIMP_BUILD_DEBUG void glTF2Importer::ImportMeshes(glTF2::Asset &r) { + ASSIMP_GLTF_LOG_DEBUG_F("Importing ", r.meshes.Size(), " meshes"); std::vector meshes; unsigned int k = 0; @@ -662,10 +664,12 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { void glTF2Importer::ImportCameras(glTF2::Asset &r) { if (!r.cameras.Size()) return; - mScene->mNumCameras = r.cameras.Size(); - mScene->mCameras = new aiCamera *[r.cameras.Size()]; + const unsigned int numCameras = r.cameras.Size(); + ASSIMP_GLTF_LOG_DEBUG_F("Importing ", numCameras, " cameras"); + mScene->mNumCameras = numCameras; + mScene->mCameras = new aiCamera *[numCameras]; - for (size_t i = 0; i < r.cameras.Size(); ++i) { + for (size_t i = 0; i < numCameras; ++i) { Camera &cam = r.cameras[i]; aiCamera *aicam = mScene->mCameras[i] = new aiCamera(); @@ -696,10 +700,12 @@ void glTF2Importer::ImportLights(glTF2::Asset &r) { if (!r.lights.Size()) return; - mScene->mNumLights = r.lights.Size(); - mScene->mLights = new aiLight *[r.lights.Size()]; + const unsigned int numLights = r.lights.Size(); + ASSIMP_GLTF_LOG_DEBUG_F("Importing ", numLights, " lights"); + mScene->mNumLights = numLights; + mScene->mLights = new aiLight *[numLights]; - for (size_t i = 0; i < r.lights.Size(); ++i) { + for (size_t i = 0; i < numLights; ++i) { Light &light = r.lights[i]; aiLight *ail = mScene->mLights[i] = new aiLight(); @@ -958,6 +964,7 @@ void glTF2Importer::ImportNodes(glTF2::Asset &r) { if (!r.scene) { throw DeadlyImportError("GLTF: No scene"); } + ASSIMP_GLTF_LOG_DEBUG("Importing nodes"); std::vector> rootNodes = r.scene->nodes; @@ -1137,13 +1144,15 @@ std::unordered_map GatherSamplers(Animation &an void glTF2Importer::ImportAnimations(glTF2::Asset &r) { if (!r.scene) return; - mScene->mNumAnimations = r.animations.Size(); + const unsigned numAnimations = r.animations.Size(); + ASSIMP_GLTF_LOG_DEBUG_F("Importing ", numAnimations, " animations"); + mScene->mNumAnimations = numAnimations; if (mScene->mNumAnimations == 0) { return; } - mScene->mAnimations = new aiAnimation *[mScene->mNumAnimations]; - for (unsigned int i = 0; i < r.animations.Size(); ++i) { + mScene->mAnimations = new aiAnimation *[numAnimations]; + for (unsigned int i = 0; i < numAnimations; ++i) { Animation &anim = r.animations[i]; aiAnimation *ai_anim = new aiAnimation(); @@ -1249,6 +1258,8 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) { if (numEmbeddedTexs == 0) return; + ASSIMP_GLTF_LOG_DEBUG_F("Importing ", numEmbeddedTexs, " embedded textures"); + mScene->mTextures = new aiTexture *[numEmbeddedTexs]; // Add the embedded textures @@ -1288,6 +1299,7 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) { } void glTF2Importer::ImportCommonMetadata(glTF2::Asset& a) { + ASSIMP_GLTF_LOG_DEBUG("Importing metadata"); ai_assert(mScene->mMetaData == nullptr); const bool hasVersion = !a.asset.version.empty(); const bool hasGenerator = !a.asset.generator.empty(); @@ -1307,6 +1319,9 @@ void glTF2Importer::ImportCommonMetadata(glTF2::Asset& a) { } void glTF2Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { + + ASSIMP_GLTF_LOG_DEBUG("Reading GLTF file"); + // clean all member arrays meshOffsets.clear(); embeddedTexIdxs.clear(); diff --git a/include/assimp/Logger.hpp b/include/assimp/Logger.hpp index a0b798564..f32c3edc2 100644 --- a/include/assimp/Logger.hpp +++ b/include/assimp/Logger.hpp @@ -273,33 +273,31 @@ 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 +// ------------------------------------------------------------------------------------------------ +#define ASSIMP_LOG_WARN_F(string, ...) \ + Assimp::DefaultLogger::get()->warn((Assimp::Formatter::format(string), __VA_ARGS__)) + +#define ASSIMP_LOG_ERROR_F(string, ...) \ + Assimp::DefaultLogger::get()->error((Assimp::Formatter::format(string), __VA_ARGS__)) + +#define ASSIMP_LOG_DEBUG_F(string, ...) \ + Assimp::DefaultLogger::get()->debug((Assimp::Formatter::format(string), __VA_ARGS__)) + +#define ASSIMP_LOG_INFO_F(string, ...) \ + Assimp::DefaultLogger::get()->info((Assimp::Formatter::format(string), __VA_ARGS__)) + +#define ASSIMP_LOG_WARN(string) \ + Assimp::DefaultLogger::get()->warn(string) + +#define ASSIMP_LOG_ERROR(string) \ + Assimp::DefaultLogger::get()->error(string) + +#define ASSIMP_LOG_DEBUG(string) \ + Assimp::DefaultLogger::get()->debug(string) + +#define ASSIMP_LOG_INFO(string) \ + Assimp::DefaultLogger::get()->info(string) + #endif // !! INCLUDED_AI_LOGGER_H From bcca3a0d794e9aded4f4d1d42be2d4219f16bd35 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Thu, 14 May 2020 17:46:33 +0100 Subject: [PATCH 04/21] No need for bespoke macros --- code/AssetLib/FBX/FBXBinaryTokenizer.cpp | 4 ++-- code/AssetLib/FBX/FBXCompileConfig.h | 6 ------ code/AssetLib/FBX/FBXDocument.cpp | 4 ++-- code/AssetLib/FBX/FBXImporter.cpp | 2 +- code/AssetLib/FBX/FBXParser.cpp | 2 +- code/AssetLib/FBX/FBXTokenizer.cpp | 2 +- code/AssetLib/glTF2/glTF2Importer.cpp | 18 +++++++++--------- 7 files changed, 16 insertions(+), 22 deletions(-) diff --git a/code/AssetLib/FBX/FBXBinaryTokenizer.cpp b/code/AssetLib/FBX/FBXBinaryTokenizer.cpp index dd84196f1..719b928bc 100644 --- a/code/AssetLib/FBX/FBXBinaryTokenizer.cpp +++ b/code/AssetLib/FBX/FBXBinaryTokenizer.cpp @@ -428,7 +428,7 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length) { ai_assert(input); - ASSIMP_FBX_LOG_DEBUG("Tokenizing binary FBX file"); + ASSIMP_LOG_DEBUG("Tokenizing binary FBX file"); if(length < 0x1b) { TokenizeError("file is too short",0); @@ -453,7 +453,7 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length) /*Result ignored*/ ReadByte(input, cursor, input + length); /*Result ignored*/ ReadByte(input, cursor, input + length); const uint32_t version = ReadWord(input, cursor, input + length); - ASSIMP_FBX_LOG_DEBUG_F("FBX version: ", version); + ASSIMP_LOG_DEBUG_F("FBX version: ", version); const bool is64bits = version >= 7500; const char *end = input + length; while (cursor < end ) { diff --git a/code/AssetLib/FBX/FBXCompileConfig.h b/code/AssetLib/FBX/FBXCompileConfig.h index 31c8a5fdd..5cdaa6960 100644 --- a/code/AssetLib/FBX/FBXCompileConfig.h +++ b/code/AssetLib/FBX/FBXCompileConfig.h @@ -75,10 +75,4 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # endif #endif -#ifndef ASSIMP_FBX_LOG_DEBUG -// These require the DefaultLogger header. -#define ASSIMP_FBX_LOG_DEBUG ASSIMP_LOG_DEBUG -#define ASSIMP_FBX_LOG_DEBUG_F ASSIMP_LOG_DEBUG_F -#endif - #endif // INCLUDED_AI_FBX_COMPILECONFIG_H diff --git a/code/AssetLib/FBX/FBXDocument.cpp b/code/AssetLib/FBX/FBXDocument.cpp index 063ad677c..bab3707d2 100644 --- a/code/AssetLib/FBX/FBXDocument.cpp +++ b/code/AssetLib/FBX/FBXDocument.cpp @@ -266,7 +266,7 @@ Document::Document(const Parser& parser, const ImportSettings& settings) : settings(settings) , parser(parser) { - ASSIMP_FBX_LOG_DEBUG("Creating FBX Document"); + ASSIMP_LOG_DEBUG("Creating FBX Document"); // Cannot use array default initialization syntax because vc8 fails on it for (auto &timeStamp : creationTimeStamp) { @@ -312,7 +312,7 @@ void Document::ReadHeader() { const Scope& shead = *ehead->Compound(); fbxVersion = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(shead,"FBXVersion",ehead),0)); - ASSIMP_FBX_LOG_DEBUG_F("FBX Version: ", fbxVersion); + ASSIMP_LOG_DEBUG_F("FBX Version: ", fbxVersion); // While we may have some success with newer files, we don't support // the older 6.n fbx format diff --git a/code/AssetLib/FBX/FBXImporter.cpp b/code/AssetLib/FBX/FBXImporter.cpp index 232f78c13..8c908be40 100644 --- a/code/AssetLib/FBX/FBXImporter.cpp +++ b/code/AssetLib/FBX/FBXImporter.cpp @@ -146,7 +146,7 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy ThrowException("Could not open file for reading"); } - ASSIMP_FBX_LOG_DEBUG("Reading FBX file"); + ASSIMP_LOG_DEBUG("Reading FBX file"); // read entire file into memory - no streaming for this, fbx // files can grow large, but the assimp output data structure diff --git a/code/AssetLib/FBX/FBXParser.cpp b/code/AssetLib/FBX/FBXParser.cpp index 04c58f70c..c47f36150 100644 --- a/code/AssetLib/FBX/FBXParser.cpp +++ b/code/AssetLib/FBX/FBXParser.cpp @@ -221,7 +221,7 @@ Parser::Parser (const TokenList& tokens, bool is_binary) , cursor(tokens.begin()) , is_binary(is_binary) { - ASSIMP_FBX_LOG_DEBUG("Parsing FBX tokens"); + ASSIMP_LOG_DEBUG("Parsing FBX tokens"); root.reset(new Scope(*this,true)); } diff --git a/code/AssetLib/FBX/FBXTokenizer.cpp b/code/AssetLib/FBX/FBXTokenizer.cpp index 1fe39a175..4117a7d3c 100644 --- a/code/AssetLib/FBX/FBXTokenizer.cpp +++ b/code/AssetLib/FBX/FBXTokenizer.cpp @@ -136,7 +136,7 @@ void ProcessDataToken( TokenList& output_tokens, const char*& start, const char* void Tokenize(TokenList& output_tokens, const char* input) { ai_assert(input); - ASSIMP_FBX_LOG_DEBUG("Tokenizing ascii FBX file"); + ASSIMP_LOG_DEBUG("Tokenizing ascii FBX file"); // line and column numbers numbers are one-based unsigned int line = 1; diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index ee6a1b298..aca86d9c5 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -286,7 +286,7 @@ static aiMaterial *ImportMaterial(std::vector &embeddedTexIdxs, Asset &r, M void glTF2Importer::ImportMaterials(glTF2::Asset &r) { const unsigned int numImportedMaterials = unsigned(r.materials.Size()); - ASSIMP_GLTF_LOG_DEBUG_F("Importing ", numImportedMaterials, " materials"); + ASSIMP_LOG_DEBUG_F("Importing ", numImportedMaterials, " materials"); Material defaultMaterial; mScene->mNumMaterials = numImportedMaterials + 1; @@ -334,7 +334,7 @@ static inline bool CheckValidFacesIndices(aiFace *faces, unsigned nFaces, unsign #endif // ASSIMP_BUILD_DEBUG void glTF2Importer::ImportMeshes(glTF2::Asset &r) { - ASSIMP_GLTF_LOG_DEBUG_F("Importing ", r.meshes.Size(), " meshes"); + ASSIMP_LOG_DEBUG_F("Importing ", r.meshes.Size(), " meshes"); std::vector meshes; unsigned int k = 0; @@ -665,7 +665,7 @@ void glTF2Importer::ImportCameras(glTF2::Asset &r) { if (!r.cameras.Size()) return; const unsigned int numCameras = r.cameras.Size(); - ASSIMP_GLTF_LOG_DEBUG_F("Importing ", numCameras, " cameras"); + ASSIMP_LOG_DEBUG_F("Importing ", numCameras, " cameras"); mScene->mNumCameras = numCameras; mScene->mCameras = new aiCamera *[numCameras]; @@ -701,7 +701,7 @@ void glTF2Importer::ImportLights(glTF2::Asset &r) { return; const unsigned int numLights = r.lights.Size(); - ASSIMP_GLTF_LOG_DEBUG_F("Importing ", numLights, " lights"); + ASSIMP_LOG_DEBUG_F("Importing ", numLights, " lights"); mScene->mNumLights = numLights; mScene->mLights = new aiLight *[numLights]; @@ -964,7 +964,7 @@ void glTF2Importer::ImportNodes(glTF2::Asset &r) { if (!r.scene) { throw DeadlyImportError("GLTF: No scene"); } - ASSIMP_GLTF_LOG_DEBUG("Importing nodes"); + ASSIMP_LOG_DEBUG("Importing nodes"); std::vector> rootNodes = r.scene->nodes; @@ -1145,7 +1145,7 @@ void glTF2Importer::ImportAnimations(glTF2::Asset &r) { if (!r.scene) return; const unsigned numAnimations = r.animations.Size(); - ASSIMP_GLTF_LOG_DEBUG_F("Importing ", numAnimations, " animations"); + ASSIMP_LOG_DEBUG_F("Importing ", numAnimations, " animations"); mScene->mNumAnimations = numAnimations; if (mScene->mNumAnimations == 0) { return; @@ -1258,7 +1258,7 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) { if (numEmbeddedTexs == 0) return; - ASSIMP_GLTF_LOG_DEBUG_F("Importing ", numEmbeddedTexs, " embedded textures"); + ASSIMP_LOG_DEBUG_F("Importing ", numEmbeddedTexs, " embedded textures"); mScene->mTextures = new aiTexture *[numEmbeddedTexs]; @@ -1299,7 +1299,7 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) { } void glTF2Importer::ImportCommonMetadata(glTF2::Asset& a) { - ASSIMP_GLTF_LOG_DEBUG("Importing metadata"); + ASSIMP_LOG_DEBUG("Importing metadata"); ai_assert(mScene->mMetaData == nullptr); const bool hasVersion = !a.asset.version.empty(); const bool hasGenerator = !a.asset.generator.empty(); @@ -1320,7 +1320,7 @@ void glTF2Importer::ImportCommonMetadata(glTF2::Asset& a) { void glTF2Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { - ASSIMP_GLTF_LOG_DEBUG("Reading GLTF file"); + ASSIMP_LOG_DEBUG("Reading GLTF file"); // clean all member arrays meshOffsets.clear(); From 2ffd1cb8db5988009cd9ad8d67ae450f6f0c7f6d Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Fri, 15 May 2020 09:29:20 +0100 Subject: [PATCH 05/21] nits --- code/AssetLib/FBX/FBXTokenizer.cpp | 2 +- code/AssetLib/glTF2/glTF2Importer.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/AssetLib/FBX/FBXTokenizer.cpp b/code/AssetLib/FBX/FBXTokenizer.cpp index 4117a7d3c..23c238d1f 100644 --- a/code/AssetLib/FBX/FBXTokenizer.cpp +++ b/code/AssetLib/FBX/FBXTokenizer.cpp @@ -136,7 +136,7 @@ void ProcessDataToken( TokenList& output_tokens, const char*& start, const char* void Tokenize(TokenList& output_tokens, const char* input) { ai_assert(input); - ASSIMP_LOG_DEBUG("Tokenizing ascii FBX file"); + ASSIMP_LOG_DEBUG("Tokenizing ASCII FBX file"); // line and column numbers numbers are one-based unsigned int line = 1; diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index aca86d9c5..83f022e8f 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -1320,7 +1320,7 @@ void glTF2Importer::ImportCommonMetadata(glTF2::Asset& a) { void glTF2Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { - ASSIMP_LOG_DEBUG("Reading GLTF file"); + ASSIMP_LOG_DEBUG("Reading GLTF2 file"); // clean all member arrays meshOffsets.clear(); From 5e0136d737ebaa6f2547c20c72dc24edb8e3d3d4 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Fri, 15 May 2020 12:47:27 +0100 Subject: [PATCH 06/21] Add concept of verboseDebug --- code/Common/Assimp.cpp | 4 ++-- code/Common/DefaultLogger.cpp | 29 +++++++++++++++++++++++++++-- include/assimp/DefaultLogger.hpp | 11 +++++++---- include/assimp/Logger.hpp | 32 ++++++++++++++++++++++++++++++-- include/assimp/NullLogger.hpp | 7 ++++++- 5 files changed, 72 insertions(+), 11 deletions(-) diff --git a/code/Common/Assimp.cpp b/code/Common/Assimp.cpp index 67f1c3af2..86ddb92c1 100644 --- a/code/Common/Assimp.cpp +++ b/code/Common/Assimp.cpp @@ -392,7 +392,7 @@ ASSIMP_API aiReturn aiDetachLogStream(const aiLogStream *stream) { if (it == gActiveLogStreams.end()) { return AI_FAILURE; } - DefaultLogger::get()->detatchStream(it->second); + DefaultLogger::get()->detachStream( it->second ); delete it->second; gActiveLogStreams.erase(it); @@ -416,7 +416,7 @@ ASSIMP_API void aiDetachAllLogStreams(void) { } for (LogStreamMap::iterator it = gActiveLogStreams.begin(); it != gActiveLogStreams.end(); ++it) { - logger->detatchStream(it->second); + logger->detachStream( it->second ); delete it->second; } gActiveLogStreams.clear(); diff --git a/code/Common/DefaultLogger.cpp b/code/Common/DefaultLogger.cpp index adb9ba160..6b2f9252b 100644 --- a/code/Common/DefaultLogger.cpp +++ b/code/Common/DefaultLogger.cpp @@ -177,6 +177,18 @@ void Logger::debug(const char* message) { return OnDebug(message); } +// ---------------------------------------------------------------------------------- +void Logger::verboseDebug(const char *message) { + + // SECURITY FIX: otherwise it's easy to produce overruns since + // sometimes importers will include data from the input file + // (i.e. node names) in their messages. + if (strlen(message) > MAX_LOG_MESSAGE_LENGTH) { + return; + } + return OnVerboseDebug(message); +} + // ---------------------------------------------------------------------------------- void Logger::info(const char* message) { @@ -251,7 +263,7 @@ void DefaultLogger::kill() { // ---------------------------------------------------------------------------------- // Debug message void DefaultLogger::OnDebug( const char* message ) { - if ( m_Severity == Logger::NORMAL ) { + if ( m_Severity < Logger::DEBUG ) { return; } @@ -262,6 +274,19 @@ void DefaultLogger::OnDebug( const char* message ) { WriteToStreams( msg, Logger::Debugging ); } +// Verbose debug message +void DefaultLogger::OnVerboseDebug(const char *message) { + if (m_Severity < Logger::VERBOSE) { + return; + } + + static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; + char msg[Size]; + ai_snprintf(msg, Size, "Debug, T%u: %s", GetThreadID(), message); + + WriteToStreams(msg, Logger::Debugging); +} + // ---------------------------------------------------------------------------------- // Logs an info void DefaultLogger::OnInfo( const char* message ){ @@ -320,7 +345,7 @@ bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity ) { // ---------------------------------------------------------------------------------- // Detach a stream -bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity ) { +bool DefaultLogger::detachStream( LogStream *pStream, unsigned int severity ) { if ( nullptr == pStream ) { return false; } diff --git a/include/assimp/DefaultLogger.hpp b/include/assimp/DefaultLogger.hpp index 789072a7c..229ace87b 100644 --- a/include/assimp/DefaultLogger.hpp +++ b/include/assimp/DefaultLogger.hpp @@ -80,7 +80,7 @@ public: /** @brief Creates a logging instance. * @param name Name for log file. Only valid in combination * with the aiDefaultLogStream_FILE flag. - * @param severity Log severity, VERBOSE turns on debug messages + * @param severity Log severity, DEBUG turns on debug messages and VERBOSE turns on all messages. * @param defStreams Default log streams to be attached. Any bitwise * combination of the aiDefaultLogStream enumerated values. * If #aiDefaultLogStream_FILE is specified but an empty string is @@ -127,8 +127,8 @@ public: unsigned int severity); // ---------------------------------------------------------------------- - /** @copydoc Logger::detatchStream */ - bool detatchStream(LogStream *pStream, + /** @copydoc Logger::detachStream */ + bool detachStream(LogStream *pStream, unsigned int severity); private: @@ -141,9 +141,12 @@ private: /** @briefDestructor */ ~DefaultLogger(); - /** @brief Logs debug infos, only been written when severity level VERBOSE is set */ + /** @brief Logs debug infos, only been written when severity level DEBUG is set */ void OnDebug(const char* message); + /** @brief Logs debug infos, only been written when severity level VERBOSE is set */ + void OnVerboseDebug(const char *message); + /** @brief Logs an info message */ void OnInfo(const char* message); diff --git a/include/assimp/Logger.hpp b/include/assimp/Logger.hpp index f32c3edc2..1e5a61eee 100644 --- a/include/assimp/Logger.hpp +++ b/include/assimp/Logger.hpp @@ -74,7 +74,8 @@ public: */ enum LogSeverity { NORMAL, //!< Normal granularity of logging - VERBOSE //!< Debug infos will be logged, too + DEBUG, //!< Debug messages will be logged, but not verbose debug messages. + VERBOSE //!< All messages will be logged }; // ---------------------------------------------------------------------- @@ -103,6 +104,12 @@ public: void debug(const char* message); void debug(const std::string &message); + // ---------------------------------------------------------------------- + /** @brief Writes a debug message + * @param message Debug message*/ + void verboseDebug(const char *message); + void verboseDebug(const std::string &message); + // ---------------------------------------------------------------------- /** @brief Writes a info message * @param message Info message*/ @@ -154,7 +161,7 @@ public: * if the result is 0 the stream is detached from the Logger and * the caller retakes the possession of the stream. * @return true if the stream has been detached, false otherwise.*/ - virtual bool detatchStream(LogStream *pStream, + virtual bool detachStream(LogStream *pStream, unsigned int severity = Debugging | Err | Warn | Info) = 0; protected: @@ -178,6 +185,16 @@ protected: */ virtual void OnDebug(const char* message)= 0; + // ---------------------------------------------------------------------- + /** + * @brief Called as a request to write a specific verbose 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 + * the function is left. + */ + virtual void OnVerboseDebug(const char *message) = 0; + // ---------------------------------------------------------------------- /** * @brief Called as a request to write a specific info message @@ -255,6 +272,11 @@ void Logger::debug(const std::string &message) { return debug(message.c_str()); } +// ---------------------------------------------------------------------------------- +inline void Logger::verboseDebug(const std::string &message) { + return verboseDebug(message.c_str()); +} + // ---------------------------------------------------------------------------------- inline void Logger::error(const std::string &message) { @@ -285,6 +307,9 @@ void Logger::info(const std::string &message) { #define ASSIMP_LOG_DEBUG_F(string, ...) \ Assimp::DefaultLogger::get()->debug((Assimp::Formatter::format(string), __VA_ARGS__)) +#define ASSIMP_LOG_VERBOSE_DEBUG_F(string, ...) \ + Assimp::DefaultLogger::get()->verboseDebug((Assimp::Formatter::format(string), __VA_ARGS__)) + #define ASSIMP_LOG_INFO_F(string, ...) \ Assimp::DefaultLogger::get()->info((Assimp::Formatter::format(string), __VA_ARGS__)) @@ -297,6 +322,9 @@ void Logger::info(const std::string &message) { #define ASSIMP_LOG_DEBUG(string) \ Assimp::DefaultLogger::get()->debug(string) +#define ASSIMP_LOG_VERBOSE_DEBUG(string) \ + Assimp::DefaultLogger::get()->verboseDebug(string) + #define ASSIMP_LOG_INFO(string) \ Assimp::DefaultLogger::get()->info(string) diff --git a/include/assimp/NullLogger.hpp b/include/assimp/NullLogger.hpp index 7effca83a..e7a01ed78 100644 --- a/include/assimp/NullLogger.hpp +++ b/include/assimp/NullLogger.hpp @@ -66,6 +66,11 @@ public: (void)message; //this avoids compiler warnings } + /** @brief Logs a verbose debug message */ + void OnVerboseDebug(const char *message) { + (void)message; //this avoids compiler warnings + } + /** @brief Logs an info message */ void OnInfo(const char* message) { (void)message; //this avoids compiler warnings @@ -88,7 +93,7 @@ public: } /** @brief Detach a still attached stream from logger */ - bool detatchStream(LogStream *pStream, unsigned int severity) { + bool detachStream(LogStream *pStream, unsigned int severity) { (void)pStream; (void)severity; //this avoids compiler warnings return false; } From e11d78596fe26f4f28e6ca56c473fc595cd7c7c4 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Fri, 15 May 2020 12:59:48 +0100 Subject: [PATCH 07/21] Use verbose debug logging in certain places --- code/Common/SceneCombiner.cpp | 2 +- code/Common/ScenePreprocessor.cpp | 8 ++++---- code/Common/Subdivision.cpp | 6 +++--- code/PostProcessing/ArmaturePopulate.cpp | 8 ++++---- code/PostProcessing/ConvertToLHProcess.cpp | 2 +- code/PostProcessing/FindDegenerates.cpp | 2 +- code/PostProcessing/ImproveCacheLocality.cpp | 2 +- code/PostProcessing/JoinVerticesProcess.cpp | 2 +- code/PostProcessing/RemoveRedundantMaterials.cpp | 2 +- include/assimp/DefaultLogger.hpp | 2 +- 10 files changed, 18 insertions(+), 18 deletions(-) diff --git a/code/Common/SceneCombiner.cpp b/code/Common/SceneCombiner.cpp index 4d2a411f2..eb802dd8b 100644 --- a/code/Common/SceneCombiner.cpp +++ b/code/Common/SceneCombiner.cpp @@ -75,7 +75,7 @@ void PrefixString(aiString& string,const char* prefix, unsigned int len) { return; if (len+string.length>=MAXLEN-1) { - ASSIMP_LOG_DEBUG("Can't add an unique prefix because the string is too long"); + ASSIMP_LOG_VERBOSE_DEBUG("Can't add an unique prefix because the string is too long"); ai_assert(false); return; } diff --git a/code/Common/ScenePreprocessor.cpp b/code/Common/ScenePreprocessor.cpp index 606590519..0cb833302 100644 --- a/code/Common/ScenePreprocessor.cpp +++ b/code/Common/ScenePreprocessor.cpp @@ -225,7 +225,7 @@ void ScenePreprocessor::ProcessAnimation (aiAnimation* anim) q.mTime = 0.; q.mValue = rotation; - ASSIMP_LOG_DEBUG("ScenePreprocessor: Dummy rotation track has been generated"); + ASSIMP_LOG_VERBOSE_DEBUG("ScenePreprocessor: Dummy rotation track has been generated"); } else { ai_assert(channel->mRotationKeys); } @@ -240,7 +240,7 @@ void ScenePreprocessor::ProcessAnimation (aiAnimation* anim) q.mTime = 0.; q.mValue = scaling; - ASSIMP_LOG_DEBUG("ScenePreprocessor: Dummy scaling track has been generated"); + ASSIMP_LOG_VERBOSE_DEBUG("ScenePreprocessor: Dummy scaling track has been generated"); } else { ai_assert(channel->mScalingKeys); } @@ -255,7 +255,7 @@ void ScenePreprocessor::ProcessAnimation (aiAnimation* anim) q.mTime = 0.; q.mValue = position; - ASSIMP_LOG_DEBUG("ScenePreprocessor: Dummy position track has been generated"); + ASSIMP_LOG_VERBOSE_DEBUG("ScenePreprocessor: Dummy position track has been generated"); } else { ai_assert(channel->mPositionKeys); } @@ -264,7 +264,7 @@ void ScenePreprocessor::ProcessAnimation (aiAnimation* anim) } if (anim->mDuration == -1.) { - ASSIMP_LOG_DEBUG("ScenePreprocessor: Setting animation duration"); + ASSIMP_LOG_VERBOSE_DEBUG("ScenePreprocessor: Setting animation duration"); anim->mDuration = last - std::min( first, 0. ); } } diff --git a/code/Common/Subdivision.cpp b/code/Common/Subdivision.cpp index 2b376695e..ca7749891 100644 --- a/code/Common/Subdivision.cpp +++ b/code/Common/Subdivision.cpp @@ -181,7 +181,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) { - ASSIMP_LOG_DEBUG("Catmull-Clark Subdivider: Skipping pure line/point mesh"); + ASSIMP_LOG_VERBOSE_DEBUG("Catmull-Clark Subdivider: Skipping pure line/point mesh"); if (discard_input) { out[s] = i; @@ -346,7 +346,7 @@ 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. - ASSIMP_LOG_DEBUG_F("Catmull-Clark Subdivider: got ", bad_cnt, " bad edges touching only one face (totally ", + ASSIMP_LOG_VERBOSE_DEBUG_F("Catmull-Clark Subdivider: got ", bad_cnt, " bad edges touching only one face (totally ", static_cast(edges.size()), " edges). "); }} @@ -405,7 +405,7 @@ void CatmullClarkSubdivider::InternSubdivide ( } ai_assert(haveit); if (!haveit) { - ASSIMP_LOG_DEBUG("Catmull-Clark Subdivider: Index not used"); + ASSIMP_LOG_VERBOSE_DEBUG("Catmull-Clark Subdivider: Index not used"); } break; } diff --git a/code/PostProcessing/ArmaturePopulate.cpp b/code/PostProcessing/ArmaturePopulate.cpp index 9065177b6..c6efeee58 100644 --- a/code/PostProcessing/ArmaturePopulate.cpp +++ b/code/PostProcessing/ArmaturePopulate.cpp @@ -82,7 +82,7 @@ void ArmaturePopulate::Execute(aiScene *out) { for (std::pair kvp : bone_stack) { aiBone *bone = kvp.first; aiNode *bone_node = kvp.second; - ASSIMP_LOG_DEBUG_F("active node lookup: ", bone->mName.C_Str()); + ASSIMP_LOG_VERBOSE_DEBUG_F("active node lookup: ", bone->mName.C_Str()); // lcl transform grab - done in generate_nodes :) // bone->mOffsetMatrix = bone_node->mTransformation; @@ -178,7 +178,7 @@ void ArmaturePopulate::BuildBoneStack(aiNode *, if (node == nullptr) { node_stack.clear(); BuildNodeList(root_node, node_stack); - ASSIMP_LOG_DEBUG_F("Resetting bone stack: nullptr element ", bone->mName.C_Str()); + ASSIMP_LOG_VERBOSE_DEBUG_F("Resetting bone stack: nullptr element ", bone->mName.C_Str()); node = GetNodeFromStack(bone->mName, node_stack); @@ -188,7 +188,7 @@ void ArmaturePopulate::BuildBoneStack(aiNode *, } } - ASSIMP_LOG_DEBUG_F("Successfully added bone[", bone->mName.C_Str(), "] to stack and bone node is: ", node->mName.C_Str()); + ASSIMP_LOG_VERBOSE_DEBUG_F("Successfully added bone[", bone->mName.C_Str(), "] to stack and bone node is: ", node->mName.C_Str()); bone_stack.insert(std::pair(bone, node)); } @@ -202,7 +202,7 @@ aiNode *ArmaturePopulate::GetArmatureRoot(aiNode *bone_node, std::vector &bone_list) { while (bone_node) { if (!IsBoneNode(bone_node->mName, bone_list)) { - ASSIMP_LOG_DEBUG_F("GetArmatureRoot() Found valid armature: ", bone_node->mName.C_Str()); + ASSIMP_LOG_VERBOSE_DEBUG_F("GetArmatureRoot() Found valid armature: ", bone_node->mName.C_Str()); return bone_node; } diff --git a/code/PostProcessing/ConvertToLHProcess.cpp b/code/PostProcessing/ConvertToLHProcess.cpp index 6ca73f10e..29c2d6a26 100644 --- a/code/PostProcessing/ConvertToLHProcess.cpp +++ b/code/PostProcessing/ConvertToLHProcess.cpp @@ -299,7 +299,7 @@ void FlipUVsProcess::ProcessMaterial (aiMaterial* _mat) for (unsigned int a = 0; a < mat->mNumProperties;++a) { aiMaterialProperty* prop = mat->mProperties[a]; if( !prop ) { - ASSIMP_LOG_DEBUG( "Property is null" ); + ASSIMP_LOG_VERBOSE_DEBUG( "Property is null" ); continue; } diff --git a/code/PostProcessing/FindDegenerates.cpp b/code/PostProcessing/FindDegenerates.cpp index dfdfec6cc..e5defdeb0 100644 --- a/code/PostProcessing/FindDegenerates.cpp +++ b/code/PostProcessing/FindDegenerates.cpp @@ -289,7 +289,7 @@ 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"); + ASSIMP_LOG_VERBOSE_DEBUG("FindDegeneratesProcess removed a mesh full of degenerated primitives"); return true; } } diff --git a/code/PostProcessing/ImproveCacheLocality.cpp b/code/PostProcessing/ImproveCacheLocality.cpp index d72d15d3a..bab1754cd 100644 --- a/code/PostProcessing/ImproveCacheLocality.cpp +++ b/code/PostProcessing/ImproveCacheLocality.cpp @@ -355,7 +355,7 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int me // very intense verbose logging ... prepare for much text if there are many meshes if ( DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) { - ASSIMP_LOG_DEBUG_F("Mesh %u | ACMR in: ", meshNum, " out: ", fACMR, " | ~", fACMR2, ((fACMR - fACMR2) / fACMR) * 100.f); + ASSIMP_LOG_VERBOSE_DEBUG_F("Mesh %u | ACMR in: ", meshNum, " out: ", fACMR, " | ~", fACMR2, ((fACMR - fACMR2) / fACMR) * 100.f); } fACMR2 *= pMesh->mNumFaces; diff --git a/code/PostProcessing/JoinVerticesProcess.cpp b/code/PostProcessing/JoinVerticesProcess.cpp index 070c9636f..4a6362e3e 100644 --- a/code/PostProcessing/JoinVerticesProcess.cpp +++ b/code/PostProcessing/JoinVerticesProcess.cpp @@ -373,7 +373,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) } if (!DefaultLogger::isNullLogger() && DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) { - ASSIMP_LOG_DEBUG_F( + ASSIMP_LOG_VERBOSE_DEBUG_F( "Mesh ",meshIndex, " (", (pMesh->mName.length ? pMesh->mName.data : "unnamed"), diff --git a/code/PostProcessing/RemoveRedundantMaterials.cpp b/code/PostProcessing/RemoveRedundantMaterials.cpp index 0c4280410..7f8b77d20 100644 --- a/code/PostProcessing/RemoveRedundantMaterials.cpp +++ b/code/PostProcessing/RemoveRedundantMaterials.cpp @@ -122,7 +122,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) // Keep this material even if no mesh references it abReferenced[i] = true; - ASSIMP_LOG_DEBUG_F( "Found positive match in exclusion list: \'", name.data, "\'"); + ASSIMP_LOG_VERBOSE_DEBUG_F( "Found positive match in exclusion list: \'", name.data, "\'"); } } } diff --git a/include/assimp/DefaultLogger.hpp b/include/assimp/DefaultLogger.hpp index 229ace87b..c405a7409 100644 --- a/include/assimp/DefaultLogger.hpp +++ b/include/assimp/DefaultLogger.hpp @@ -141,7 +141,7 @@ private: /** @briefDestructor */ ~DefaultLogger(); - /** @brief Logs debug infos, only been written when severity level DEBUG is set */ + /** @brief Logs debug infos, only been written when severity level DEBUG or higher is set */ void OnDebug(const char* message); /** @brief Logs debug infos, only been written when severity level VERBOSE is set */ From 434c5e3d37478d438698fae591382e1f4a561ffa Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Fri, 15 May 2020 16:59:42 +0100 Subject: [PATCH 08/21] More verbose logging --- code/AssetLib/3DS/3DSConverter.cpp | 4 ++-- code/AssetLib/AC/ACLoader.cpp | 4 ++-- code/AssetLib/ASE/ASELoader.cpp | 2 +- code/AssetLib/Blender/BlenderDNA.cpp | 2 +- code/AssetLib/COB/COBLoader.cpp | 2 +- code/AssetLib/Collada/ColladaParser.cpp | 2 +- code/AssetLib/DXF/DXFHelper.h | 2 +- code/AssetLib/DXF/DXFLoader.cpp | 6 +++--- code/AssetLib/FBX/FBXMaterial.cpp | 2 +- code/AssetLib/LWO/LWOLoader.cpp | 2 +- code/AssetLib/LWO/LWOMaterial.cpp | 2 +- code/AssetLib/LWS/LWSLoader.cpp | 2 +- code/AssetLib/MD3/MD3Loader.cpp | 2 +- code/AssetLib/Ogre/OgreBinarySerializer.cpp | 14 +++++++------- 14 files changed, 24 insertions(+), 24 deletions(-) diff --git a/code/AssetLib/3DS/3DSConverter.cpp b/code/AssetLib/3DS/3DSConverter.cpp index 1004c74a5..ef37e03de 100644 --- a/code/AssetLib/3DS/3DSConverter.cpp +++ b/code/AssetLib/3DS/3DSConverter.cpp @@ -539,7 +539,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut, ai_assert(nullptr != anim); if (pcIn->aCameraRollKeys.size() > 1) { - ASSIMP_LOG_DEBUG("3DS: Converting camera roll track ..."); + ASSIMP_LOG_VERBOSE_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 @@ -558,7 +558,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut, #if 0 if (pcIn->aTargetPositionKeys.size() > 1) { - ASSIMP_LOG_DEBUG("3DS: Converting target track ..."); + ASSIMP_LOG_VERBOSE_DEBUG("3DS: Converting target track ..."); // Camera or spot light - need to convert the separate // target position channel to our representation diff --git a/code/AssetLib/AC/ACLoader.cpp b/code/AssetLib/AC/ACLoader.cpp index 40ff8dc86..2b8b7f087 100644 --- a/code/AssetLib/AC/ACLoader.cpp +++ b/code/AssetLib/AC/ACLoader.cpp @@ -207,7 +207,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); - ASSIMP_LOG_DEBUG("AC3D: Light source encountered"); + ASSIMP_LOG_VERBOSE_DEBUG("AC3D: Light source encountered"); obj.type = Object::Light; } else if (!ASSIMP_strincmp(buffer, "group", 5)) { obj.type = Object::Group; @@ -294,7 +294,7 @@ void AC3DImporter::LoadObjectSection(std::vector &objects) { // example writes no surf chunks if (!Q3DWorkAround) { ASSIMP_LOG_WARN("AC3D: SURF token was expected"); - ASSIMP_LOG_DEBUG("Continuing with Quick3D Workaround enabled"); + ASSIMP_LOG_VERBOSE_DEBUG("Continuing with Quick3D Workaround enabled"); } --buffer; // make sure the line is processed a second time // break; --- see fix notes above diff --git a/code/AssetLib/ASE/ASELoader.cpp b/code/AssetLib/ASE/ASELoader.cpp index 47b357248..a27767229 100644 --- a/code/AssetLib/ASE/ASELoader.cpp +++ b/code/AssetLib/ASE/ASELoader.cpp @@ -614,7 +614,7 @@ void ASEImporter::AddNodes(const std::vector &nodes, node->mNumChildren++; // What we did is so great, it is at least worth a debug message - ASSIMP_LOG_DEBUG("ASE: Generating separate target node (" + snode->mName + ")"); + ASSIMP_LOG_VERBOSE_DEBUG("ASE: Generating separate target node (" + snode->mName + ")"); } } diff --git a/code/AssetLib/Blender/BlenderDNA.cpp b/code/AssetLib/Blender/BlenderDNA.cpp index 69f139ec5..920362f24 100644 --- a/code/AssetLib/Blender/BlenderDNA.cpp +++ b/code/AssetLib/Blender/BlenderDNA.cpp @@ -353,7 +353,7 @@ void SectionParser ::Next() { } #ifdef ASSIMP_BUILD_BLENDER_DEBUG - ASSIMP_LOG_DEBUG(current.id); + ASSIMP_LOG_VERBOSE_DEBUG(current.id); #endif } diff --git a/code/AssetLib/COB/COBLoader.cpp b/code/AssetLib/COB/COBLoader.cpp index d66fb4f4c..52273d9e1 100644 --- a/code/AssetLib/COB/COBLoader.cpp +++ b/code/AssetLib/COB/COBLoader.cpp @@ -290,7 +290,7 @@ aiNode *COBImporter::BuildNodes(const Node &root, const Scene &scin, aiScene *fi } std::unique_ptr defmat; if (!min) { - ASSIMP_LOG_DEBUG(format() << "Could not resolve material index " + ASSIMP_LOG_VERBOSE_DEBUG(format() << "Could not resolve material index " << reflist.first << " - creating default material for this slot"); defmat.reset(min = new Material()); diff --git a/code/AssetLib/Collada/ColladaParser.cpp b/code/AssetLib/Collada/ColladaParser.cpp index d83980929..de3bcd47a 100644 --- a/code/AssetLib/Collada/ColladaParser.cpp +++ b/code/AssetLib/Collada/ColladaParser.cpp @@ -284,7 +284,7 @@ void ColladaParser::ReadContents() { ReadStructure(); } else { - ASSIMP_LOG_DEBUG_F("Ignoring global element <", mReader->getNodeName(), ">."); + ASSIMP_LOG_VERBOSE_DEBUG_F("Ignoring global element <", mReader->getNodeName(), ">."); SkipElement(); } } else { diff --git a/code/AssetLib/DXF/DXFHelper.h b/code/AssetLib/DXF/DXFHelper.h index 8140d00c6..d11addc0a 100644 --- a/code/AssetLib/DXF/DXFHelper.h +++ b/code/AssetLib/DXF/DXFHelper.h @@ -135,7 +135,7 @@ public: for(;splitter->length() && splitter->at(0) != '}'; splitter++, cnt++); splitter++; - ASSIMP_LOG_DEBUG((Formatter::format("DXF: skipped over control group ("),cnt," lines)")); + ASSIMP_LOG_VERBOSE_DEBUG((Formatter::format("DXF: skipped over control group ("),cnt," lines)")); } } catch(std::logic_error&) { ai_assert(!splitter); diff --git a/code/AssetLib/DXF/DXFLoader.cpp b/code/AssetLib/DXF/DXFLoader.cpp index bd5c23c7b..97b0d19dd 100644 --- a/code/AssetLib/DXF/DXFLoader.cpp +++ b/code/AssetLib/DXF/DXFLoader.cpp @@ -241,7 +241,7 @@ void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output) { } } - ASSIMP_LOG_DEBUG_F("DXF: Unexpanded polycount is ", icount, ", vertex count is ", vcount); + ASSIMP_LOG_VERBOSE_DEBUG_F("DXF: Unexpanded polycount is ", icount, ", vertex count is ", vcount); } if (! output.blocks.size() ) { @@ -473,7 +473,7 @@ void DXFImporter::ParseBlocks(DXF::LineReader& reader, DXF::FileData& output) { ++reader; } - ASSIMP_LOG_DEBUG_F("DXF: got ", output.blocks.size()," entries in BLOCKS" ); + ASSIMP_LOG_VERBOSE_DEBUG_F("DXF: got ", output.blocks.size()," entries in BLOCKS" ); } // ------------------------------------------------------------------------------------------------ @@ -549,7 +549,7 @@ void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output) ++reader; } - ASSIMP_LOG_DEBUG_F( "DXF: got ", block.lines.size()," polylines and ", block.insertions.size(), + ASSIMP_LOG_VERBOSE_DEBUG_F( "DXF: got ", block.lines.size()," polylines and ", block.insertions.size(), " inserted blocks in ENTITIES" ); } diff --git a/code/AssetLib/FBX/FBXMaterial.cpp b/code/AssetLib/FBX/FBXMaterial.cpp index 6de44bd23..9679e62a5 100644 --- a/code/AssetLib/FBX/FBXMaterial.cpp +++ b/code/AssetLib/FBX/FBXMaterial.cpp @@ -383,7 +383,7 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std } catch (const runtime_error& runtimeError) { //we don't need the content data for contents that has already been loaded - ASSIMP_LOG_DEBUG_F("Caught exception in FBXMaterial (likely because content was already loaded): ", + ASSIMP_LOG_VERBOSE_DEBUG_F("Caught exception in FBXMaterial (likely because content was already loaded): ", runtimeError.what()); } } diff --git a/code/AssetLib/LWO/LWOLoader.cpp b/code/AssetLib/LWO/LWOLoader.cpp index 7a9738228..c0431c2d9 100644 --- a/code/AssetLib/LWO/LWOLoader.cpp +++ b/code/AssetLib/LWO/LWOLoader.cpp @@ -422,7 +422,7 @@ void LWOImporter::InternReadFile(const std::string &pFile, // So we use a separate implementation. ComputeNormals(mesh, smoothingGroups, _mSurfaces[j]); } else { - ASSIMP_LOG_DEBUG("LWO2: No need to compute normals, they're already there"); + ASSIMP_LOG_VERBOSE_DEBUG("LWO2: No need to compute normals, they're already there"); } ++p; } diff --git a/code/AssetLib/LWO/LWOMaterial.cpp b/code/AssetLib/LWO/LWOMaterial.cpp index 65fcebddb..d7b08011f 100644 --- a/code/AssetLib/LWO/LWOMaterial.cpp +++ b/code/AssetLib/LWO/LWOMaterial.cpp @@ -154,7 +154,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)); } - ASSIMP_LOG_DEBUG("LWO2: Setting up non-UV mapping"); + ASSIMP_LOG_VERBOSE_DEBUG("LWO2: Setting up non-UV mapping"); } // The older LWOB format does not use indirect references to clips. diff --git a/code/AssetLib/LWS/LWSLoader.cpp b/code/AssetLib/LWS/LWSLoader.cpp index baa90d786..6e4d759ac 100644 --- a/code/AssetLib/LWS/LWSLoader.cpp +++ b/code/AssetLib/LWS/LWSLoader.cpp @@ -101,7 +101,7 @@ void LWS::Element::Parse(const char *&buffer) { SkipSpaces(&buffer); if (children.back().tokens[0] == "Plugin") { - ASSIMP_LOG_DEBUG("LWS: Skipping over plugin-specific data"); + ASSIMP_LOG_VERBOSE_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/AssetLib/MD3/MD3Loader.cpp b/code/AssetLib/MD3/MD3Loader.cpp index 30be0276e..e8176865c 100644 --- a/code/AssetLib/MD3/MD3Loader.cpp +++ b/code/AssetLib/MD3/MD3Loader.cpp @@ -888,7 +888,7 @@ void MD3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOS if (it != skins.textures.end()) { texture_name = &*( _texture_name = (*it).second).begin(); - ASSIMP_LOG_DEBUG_F("MD3: Assigning skin texture ", (*it).second, " to surface ", pcSurfaces->NAME); + ASSIMP_LOG_VERBOSE_DEBUG_F("MD3: Assigning skin texture ", (*it).second, " to surface ", pcSurfaces->NAME); (*it).resolved = true; // mark entry as resolved } diff --git a/code/AssetLib/Ogre/OgreBinarySerializer.cpp b/code/AssetLib/Ogre/OgreBinarySerializer.cpp index bc12b6403..ce412d791 100644 --- a/code/AssetLib/Ogre/OgreBinarySerializer.cpp +++ b/code/AssetLib/Ogre/OgreBinarySerializer.cpp @@ -168,7 +168,7 @@ void OgreBinarySerializer::RollbackHeader() { void OgreBinarySerializer::SkipBytes(size_t numBytes) { #if (OGRE_BINARY_SERIALIZER_DEBUG == 1) - ASSIMP_LOG_DEBUG_F("Skipping ", numBytes, " bytes"); + ASSIMP_LOG_VERBOSE_DEBUG_F("Skipping ", numBytes, " bytes"); #endif m_reader->IncPtr(numBytes); @@ -207,8 +207,8 @@ Mesh *OgreBinarySerializer::ImportMesh(MemoryStreamReader *stream) { void OgreBinarySerializer::ReadMesh(Mesh *mesh) { mesh->hasSkeletalAnimations = Read(); - ASSIMP_LOG_DEBUG("Reading Mesh"); - ASSIMP_LOG_DEBUG_F(" - Skeletal animations: ", mesh->hasSkeletalAnimations ? "true" : "false"); + ASSIMP_LOG_VERBOSE_DEBUG("Reading Mesh"); + ASSIMP_LOG_VERBOSE_DEBUG_F(" - Skeletal animations: ", mesh->hasSkeletalAnimations ? "true" : "false"); if (!AtEnd()) { uint16_t id = ReadHeader(); @@ -364,9 +364,9 @@ void OgreBinarySerializer::ReadSubMesh(Mesh *mesh) { submesh->indexData->faceCount = static_cast(submesh->indexData->count / 3); submesh->indexData->is32bit = Read(); - 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"); + ASSIMP_LOG_VERBOSE_DEBUG_F("Reading SubMesh ", mesh->subMeshes.size()); + ASSIMP_LOG_VERBOSE_DEBUG_F(" - Material: '", submesh->materialRef, "'"); + ASSIMP_LOG_VERBOSE_DEBUG_F(" - Uses shared geometry: ", submesh->usesSharedVertexData ? "true" : "false"); // Index buffer if (submesh->indexData->count > 0) { @@ -374,7 +374,7 @@ void OgreBinarySerializer::ReadSubMesh(Mesh *mesh) { uint8_t *indexBuffer = ReadBytes(numBytes); submesh->indexData->buffer = MemoryStreamPtr(new Assimp::MemoryIOStream(indexBuffer, numBytes, true)); - ASSIMP_LOG_DEBUG_F(" - ", submesh->indexData->faceCount, + ASSIMP_LOG_VERBOSE_DEBUG_F(" - ", submesh->indexData->faceCount, " faces from ", submesh->indexData->count, (submesh->indexData->is32bit ? " 32bit" : " 16bit"), " indexes of ", numBytes, " bytes"); } From 90cdbd9d9ac915732f538fa30319b64fc4ad008a Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Fri, 15 May 2020 17:46:50 +0100 Subject: [PATCH 09/21] Fix ups --- code/AssetLib/FBX/FBXConverter.cpp | 4 ++-- code/AssetLib/glTF2/glTF2Asset.inl | 4 +++- code/PostProcessing/ArmaturePopulate.cpp | 6 +++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/code/AssetLib/FBX/FBXConverter.cpp b/code/AssetLib/FBX/FBXConverter.cpp index cf50c715b..de0ed7745 100644 --- a/code/AssetLib/FBX/FBXConverter.cpp +++ b/code/AssetLib/FBX/FBXConverter.cpp @@ -1542,10 +1542,10 @@ void FBXConverter::ConvertCluster(std::vector &local_mesh_bones, const aiBone *bone = nullptr; if (bone_map.count(deformer_name)) { - ASSIMP_LOG_DEBUG_F("retrieved bone from lookup ", bone_name.C_Str(), ". Deformer:", deformer_name); + ASSIMP_LOG_VERBOSE_DEBUG_F("retrieved bone from lookup ", bone_name.C_Str(), ". Deformer:", deformer_name); bone = bone_map[deformer_name]; } else { - ASSIMP_LOG_DEBUG_F("created new bone ", bone_name.C_Str(), ". Deformer: ", deformer_name); + ASSIMP_LOG_VERBOSE_DEBUG_F("created new bone ", bone_name.C_Str(), ". Deformer: ", deformer_name); bone = new aiBone(); bone->mName = bone_name; diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index 5e1cc42d6..2735d0dc6 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -1337,6 +1337,7 @@ inline void AssetMetadata::Read(Document &doc) { // inline void Asset::ReadBinaryHeader(IOStream &stream, std::vector &sceneData) { + ASSIMP_LOG_DEBUG("Reading GLTF2 binary"); GLB_Header header; if (stream.Read(&header, sizeof(header), 1) != 1) { throw DeadlyImportError("GLTF: Unable to read the file header"); @@ -1400,6 +1401,7 @@ inline void Asset::ReadBinaryHeader(IOStream &stream, std::vector &sceneDa } inline void Asset::Load(const std::string &pFile, bool isBinary) { + ASSIMP_LOG_DEBUG("Loading GLTF2 asset"); mCurrentAssetDir.clear(); /*int pos = std::max(int(pFile.rfind('/')), int(pFile.rfind('\\'))); if (pos != int(std::string::npos)) */ @@ -1431,7 +1433,7 @@ inline void Asset::Load(const std::string &pFile, bool isBinary) { } // parse the JSON document - + ASSIMP_LOG_DEBUG("Parsing GLTF2 JSON"); Document doc; doc.ParseInsitu(&sceneData[0]); diff --git a/code/PostProcessing/ArmaturePopulate.cpp b/code/PostProcessing/ArmaturePopulate.cpp index c6efeee58..97feca31c 100644 --- a/code/PostProcessing/ArmaturePopulate.cpp +++ b/code/PostProcessing/ArmaturePopulate.cpp @@ -178,7 +178,7 @@ void ArmaturePopulate::BuildBoneStack(aiNode *, if (node == nullptr) { node_stack.clear(); BuildNodeList(root_node, node_stack); - ASSIMP_LOG_VERBOSE_DEBUG_F("Resetting bone stack: nullptr element ", bone->mName.C_Str()); + ASSIMP_LOG_VERBOSE_DEBUG_F("Resetting bone stack: nullptr element ", bone->mName.C_Str()); node = GetNodeFromStack(bone->mName, node_stack); @@ -188,7 +188,7 @@ void ArmaturePopulate::BuildBoneStack(aiNode *, } } - ASSIMP_LOG_VERBOSE_DEBUG_F("Successfully added bone[", bone->mName.C_Str(), "] to stack and bone node is: ", node->mName.C_Str()); + ASSIMP_LOG_VERBOSE_DEBUG_F("Successfully added bone[", bone->mName.C_Str(), "] to stack and bone node is: ", node->mName.C_Str()); bone_stack.insert(std::pair(bone, node)); } @@ -202,7 +202,7 @@ aiNode *ArmaturePopulate::GetArmatureRoot(aiNode *bone_node, std::vector &bone_list) { while (bone_node) { if (!IsBoneNode(bone_node->mName, bone_list)) { - ASSIMP_LOG_VERBOSE_DEBUG_F("GetArmatureRoot() Found valid armature: ", bone_node->mName.C_Str()); + ASSIMP_LOG_VERBOSE_DEBUG_F("GetArmatureRoot() Found valid armature: ", bone_node->mName.C_Str()); return bone_node; } From d70685d37fe7a00a01ea5fa5fe69371f05708836 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Fri, 15 May 2020 17:50:48 +0100 Subject: [PATCH 10/21] Fix typo --- code/AssetLib/FBX/FBXConverter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/AssetLib/FBX/FBXConverter.cpp b/code/AssetLib/FBX/FBXConverter.cpp index de0ed7745..fff617683 100644 --- a/code/AssetLib/FBX/FBXConverter.cpp +++ b/code/AssetLib/FBX/FBXConverter.cpp @@ -105,7 +105,7 @@ FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBo // The idea here is to traverse all objects to find these Textures and convert them, // so later during material conversion it will find converted texture in the textures_converted array. if (doc.Settings().readTextures) { - ConvertOrphantEmbeddedTextures(); + ConvertOrphanedEmbeddedTextures(); } ConvertRootNode(); @@ -3467,7 +3467,7 @@ void FBXConverter::TransferDataToScene() { } } -void FBXConverter::ConvertOrphantEmbeddedTextures() { +void FBXConverter::ConvertOrphanedEmbeddedTextures() { // in C++14 it could be: // for (auto&& [id, object] : objects) for (auto &&id_and_object : doc.Objects()) { From 87a7662bee8378ce9afc84bdec242cd3ae9ba212 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Mon, 18 May 2020 11:45:00 +0100 Subject: [PATCH 11/21] More thinks using VERBOSE_DEBUG --- code/AssetLib/3MF/D3MFOpcPackage.cpp | 2 +- code/AssetLib/Ogre/OgreBinarySerializer.cpp | 18 +++++------ code/AssetLib/Ogre/OgreMaterial.cpp | 18 +++++------ code/AssetLib/Ogre/OgreXmlSerializer.cpp | 34 ++++++++++----------- code/AssetLib/Ply/PlyParser.cpp | 28 ++++++++--------- code/PostProcessing/TriangulateProcess.cpp | 2 +- 6 files changed, 51 insertions(+), 51 deletions(-) diff --git a/code/AssetLib/3MF/D3MFOpcPackage.cpp b/code/AssetLib/3MF/D3MFOpcPackage.cpp index 565790656..64300ed83 100644 --- a/code/AssetLib/3MF/D3MFOpcPackage.cpp +++ b/code/AssetLib/3MF/D3MFOpcPackage.cpp @@ -147,7 +147,7 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile) } } - ASSIMP_LOG_DEBUG(rootFile); + ASSIMP_LOG_VERBOSE_DEBUG(rootFile); mZipArchive->Close(fileStream); diff --git a/code/AssetLib/Ogre/OgreBinarySerializer.cpp b/code/AssetLib/Ogre/OgreBinarySerializer.cpp index ce412d791..360da898f 100644 --- a/code/AssetLib/Ogre/OgreBinarySerializer.cpp +++ b/code/AssetLib/Ogre/OgreBinarySerializer.cpp @@ -475,7 +475,7 @@ void OgreBinarySerializer::ReadSubMeshNames(Mesh *mesh) { } submesh->name = ReadLine(); - ASSIMP_LOG_DEBUG_F(" - SubMesh ", submesh->index, " name '", submesh->name, "'"); + ASSIMP_LOG_VERBOSE_DEBUG_F(" - SubMesh ", submesh->index, " name '", submesh->name, "'"); if (!AtEnd()) id = ReadHeader(); @@ -488,7 +488,7 @@ void OgreBinarySerializer::ReadSubMeshNames(Mesh *mesh) { void OgreBinarySerializer::ReadGeometry(VertexData *dest) { dest->count = Read(); - ASSIMP_LOG_DEBUG_F(" - Reading geometry of ", dest->count, " vertices"); + ASSIMP_LOG_VERBOSE_DEBUG_F(" - Reading geometry of ", dest->count, " vertices"); if (!AtEnd()) { uint16_t id = ReadHeader(); @@ -536,7 +536,7 @@ void OgreBinarySerializer::ReadGeometryVertexElement(VertexData *dest) { element.offset = Read(); element.index = Read(); - ASSIMP_LOG_DEBUG_F(" - Vertex element ", element.SemanticToString(), " of type ", + ASSIMP_LOG_VERBOSE_DEBUG_F(" - Vertex element ", element.SemanticToString(), " of type ", element.TypeToString(), " index=", element.index, " source=", element.source); dest->vertexElements.push_back(element); @@ -557,7 +557,7 @@ void OgreBinarySerializer::ReadGeometryVertexBuffer(VertexData *dest) { uint8_t *vertexBuffer = ReadBytes(numBytes); dest->vertexBindings[bindIndex] = MemoryStreamPtr(new Assimp::MemoryIOStream(vertexBuffer, numBytes, true)); - ASSIMP_LOG_DEBUG_F(" - Read vertex buffer for source ", bindIndex, " of ", numBytes, " bytes"); + ASSIMP_LOG_VERBOSE_DEBUG_F(" - Read vertex buffer for source ", bindIndex, " of ", numBytes, " bytes"); } void OgreBinarySerializer::ReadEdgeList(Mesh * /*mesh*/) { @@ -807,7 +807,7 @@ void OgreBinarySerializer::ReadSkeleton(Skeleton *skeleton) { << " Supported versions: " << SKELETON_VERSION_1_8 << " and " << SKELETON_VERSION_1_1); } - ASSIMP_LOG_DEBUG("Reading Skeleton"); + ASSIMP_LOG_VERBOSE_DEBUG("Reading Skeleton"); bool firstBone = true; bool firstAnim = true; @@ -821,7 +821,7 @@ void OgreBinarySerializer::ReadSkeleton(Skeleton *skeleton) { } case SKELETON_BONE: { if (firstBone) { - ASSIMP_LOG_DEBUG(" - Bones"); + ASSIMP_LOG_VERBOSE_DEBUG(" - Bones"); firstBone = false; } @@ -834,7 +834,7 @@ void OgreBinarySerializer::ReadSkeleton(Skeleton *skeleton) { } case SKELETON_ANIMATION: { if (firstAnim) { - ASSIMP_LOG_DEBUG(" - Animations"); + ASSIMP_LOG_VERBOSE_DEBUG(" - Animations"); firstAnim = false; } @@ -874,7 +874,7 @@ void OgreBinarySerializer::ReadBone(Skeleton *skeleton) { throw DeadlyImportError(Formatter::format() << "Ogre Skeleton bone indexes not contiguous. Error at bone index " << bone->id); } - ASSIMP_LOG_DEBUG_F(" ", bone->id, " ", bone->name); + ASSIMP_LOG_VERBOSE_DEBUG_F(" ", bone->id, " ", bone->name); skeleton->bones.push_back(bone); } @@ -919,7 +919,7 @@ void OgreBinarySerializer::ReadSkeletonAnimation(Skeleton *skeleton) { skeleton->animations.push_back(anim); - ASSIMP_LOG_DEBUG_F(" ", anim->name, " (", anim->length, " sec, ", anim->tracks.size(), " tracks)"); + ASSIMP_LOG_VERBOSE_DEBUG_F(" ", anim->name, " (", anim->length, " sec, ", anim->tracks.size(), " tracks)"); } void OgreBinarySerializer::ReadSkeletonAnimationTrack(Skeleton * /*skeleton*/, Animation *dest) { diff --git a/code/AssetLib/Ogre/OgreMaterial.cpp b/code/AssetLib/Ogre/OgreMaterial.cpp index f79206406..74e5eb760 100644 --- a/code/AssetLib/Ogre/OgreMaterial.cpp +++ b/code/AssetLib/Ogre/OgreMaterial.cpp @@ -175,7 +175,7 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste if (materialFile) { break; } - ASSIMP_LOG_DEBUG_F( "Source file for material '", materialName, "' ", potentialFiles[i], " does not exist"); + ASSIMP_LOG_VERBOSE_DEBUG_F( "Source file for material '", materialName, "' ", potentialFiles[i], " does not exist"); } if (!materialFile) { @@ -201,7 +201,7 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste ss << &data[0]; } - ASSIMP_LOG_DEBUG_F("Reading material '", materialName, "'"); + ASSIMP_LOG_VERBOSE_DEBUG_F("Reading material '", materialName, "'"); aiMaterial *material = new aiMaterial(); m_textures.clear(); @@ -245,7 +245,7 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste return material; } - ASSIMP_LOG_DEBUG_F("material '", materialName, "'"); + ASSIMP_LOG_VERBOSE_DEBUG_F("material '", materialName, "'"); while(linePart != partBlockEnd) { @@ -353,7 +353,7 @@ bool OgreImporter::ReadTechnique(const std::string &techniqueName, stringstream return false; } - ASSIMP_LOG_DEBUG_F(" technique '", techniqueName, "'"); + ASSIMP_LOG_VERBOSE_DEBUG_F(" technique '", techniqueName, "'"); const string partPass = "pass"; @@ -389,7 +389,7 @@ bool OgreImporter::ReadPass(const std::string &passName, stringstream &ss, aiMat return false; } - ASSIMP_LOG_DEBUG_F(" pass '", passName, "'"); + ASSIMP_LOG_VERBOSE_DEBUG_F(" pass '", passName, "'"); const string partAmbient = "ambient"; const string partDiffuse = "diffuse"; @@ -416,7 +416,7 @@ bool OgreImporter::ReadPass(const std::string &passName, stringstream &ss, aiMat ss >> r >> g >> b; const aiColor3D color(r, g, b); - ASSIMP_LOG_DEBUG_F( " ", linePart, " ", r, " ", g, " ", b); + ASSIMP_LOG_VERBOSE_DEBUG_F( " ", linePart, " ", r, " ", g, " ", b); if (linePart == partAmbient) { @@ -455,7 +455,7 @@ bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstr return false; } - ASSIMP_LOG_DEBUG_F(" texture_unit '", textureUnitName, "'"); + ASSIMP_LOG_VERBOSE_DEBUG_F(" texture_unit '", textureUnitName, "'"); const string partTexture = "texture"; const string partTextCoordSet = "tex_coord_set"; @@ -490,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)); - ASSIMP_LOG_DEBUG_F( "Detecting texture type from filename postfix '", identifier, "'"); + ASSIMP_LOG_VERBOSE_DEBUG_F( "Detecting texture type from filename postfix '", identifier, "'"); if (identifier == "_n" || identifier == "_nrm" || identifier == "_nrml" || identifier == "_normal" || identifier == "_normals" || identifier == "_normalmap") { @@ -580,7 +580,7 @@ bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstr unsigned int textureTypeIndex = m_textures[textureType]; m_textures[textureType]++; - ASSIMP_LOG_DEBUG_F( " texture '", textureRef, "' type ", textureType, + ASSIMP_LOG_VERBOSE_DEBUG_F( " texture '", textureRef, "' type ", textureType, " index ", textureTypeIndex, " UV ", uvCoord); aiString assimpTextureRef(textureRef); diff --git a/code/AssetLib/Ogre/OgreXmlSerializer.cpp b/code/AssetLib/Ogre/OgreXmlSerializer.cpp index 406220a9d..31c2ee74e 100644 --- a/code/AssetLib/Ogre/OgreXmlSerializer.cpp +++ b/code/AssetLib/Ogre/OgreXmlSerializer.cpp @@ -268,7 +268,7 @@ void OgreXmlSerializer::ReadMesh(MeshXml *mesh) { throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting "); } - ASSIMP_LOG_DEBUG("Reading Mesh"); + ASSIMP_LOG_VERBOSE_DEBUG("Reading Mesh"); NextNode(); @@ -294,7 +294,7 @@ void OgreXmlSerializer::ReadMesh(MeshXml *mesh) { ReadBoneAssignments(mesh->sharedVertexData); } else if (m_currentNodeName == nnSkeletonLink) { mesh->skeletonRef = ReadAttribute("name"); - ASSIMP_LOG_DEBUG_F("Read skeleton link ", mesh->skeletonRef); + ASSIMP_LOG_VERBOSE_DEBUG_F("Read skeleton link ", mesh->skeletonRef); NextNode(); } // Assimp incompatible/ignored nodes @@ -305,7 +305,7 @@ void OgreXmlSerializer::ReadMesh(MeshXml *mesh) { void OgreXmlSerializer::ReadGeometry(VertexDataXml *dest) { dest->count = ReadAttribute("vertexcount"); - ASSIMP_LOG_DEBUG_F(" - Reading geometry of ", dest->count, " vertices"); + ASSIMP_LOG_VERBOSE_DEBUG_F(" - Reading geometry of ", dest->count, " vertices"); NextNode(); while (m_currentNodeName == nnVertexBuffer) { @@ -325,19 +325,19 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest) { } if (positions) { - ASSIMP_LOG_DEBUG(" - Contains positions"); + ASSIMP_LOG_VERBOSE_DEBUG(" - Contains positions"); dest->positions.reserve(dest->count); } if (normals) { - ASSIMP_LOG_DEBUG(" - Contains normals"); + ASSIMP_LOG_VERBOSE_DEBUG(" - Contains normals"); dest->normals.reserve(dest->count); } if (tangents) { - ASSIMP_LOG_DEBUG(" - Contains tangents"); + ASSIMP_LOG_VERBOSE_DEBUG(" - Contains tangents"); dest->tangents.reserve(dest->count); } if (uvs > 0) { - ASSIMP_LOG_DEBUG_F(" - Contains ", uvs, " texture coords"); + ASSIMP_LOG_VERBOSE_DEBUG_F(" - Contains ", uvs, " texture coords"); dest->uvs.resize(uvs); for (size_t i = 0, len = dest->uvs.size(); i < len; ++i) { dest->uvs[i].reserve(dest->count); @@ -464,9 +464,9 @@ void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh) { submesh->usesSharedVertexData = ReadAttribute(anUseSharedVertices); } - 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")); + ASSIMP_LOG_VERBOSE_DEBUG_F("Reading SubMesh ", mesh->subMeshes.size()); + ASSIMP_LOG_VERBOSE_DEBUG_F(" - Material: '", submesh->materialRef, "'"); + ASSIMP_LOG_VERBOSE_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 @@ -505,7 +505,7 @@ void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh) { } if (submesh->indexData->faces.size() == submesh->indexData->faceCount) { - ASSIMP_LOG_DEBUG_F(" - Faces ", submesh->indexData->faceCount); + ASSIMP_LOG_VERBOSE_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); } @@ -571,7 +571,7 @@ void OgreXmlSerializer::ReadBoneAssignments(VertexDataXml *dest) { } } - ASSIMP_LOG_DEBUG_F(" - ", dest->boneAssignments.size(), " bone assignments"); + ASSIMP_LOG_VERBOSE_DEBUG_F(" - ", dest->boneAssignments.size(), " bone assignments"); } // Skeleton @@ -648,7 +648,7 @@ void OgreXmlSerializer::ReadSkeleton(Skeleton *skeleton) { throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting "); } - ASSIMP_LOG_DEBUG("Reading Skeleton"); + ASSIMP_LOG_VERBOSE_DEBUG("Reading Skeleton"); // Optional blend mode from root node if (HasAttribute("blendmode")) { @@ -678,7 +678,7 @@ void OgreXmlSerializer::ReadAnimations(Skeleton *skeleton) { throw DeadlyImportError("Cannot read for a Skeleton without bones"); } - ASSIMP_LOG_DEBUG(" - Animations"); + ASSIMP_LOG_VERBOSE_DEBUG(" - Animations"); NextNode(); while (m_currentNodeName == nnAnimation) { @@ -693,7 +693,7 @@ void OgreXmlSerializer::ReadAnimations(Skeleton *skeleton) { ReadAnimationTracks(anim); skeleton->animations.push_back(anim); - ASSIMP_LOG_DEBUG_F(" ", anim->name, " (", anim->length, " sec, ", anim->tracks.size(), " tracks)"); + ASSIMP_LOG_VERBOSE_DEBUG_F(" ", anim->name, " (", anim->length, " sec, ", anim->tracks.size(), " tracks)"); } } @@ -793,7 +793,7 @@ static bool BoneCompare(Bone *a, Bone *b) { } void OgreXmlSerializer::ReadBones(Skeleton *skeleton) { - ASSIMP_LOG_DEBUG(" - Bones"); + ASSIMP_LOG_VERBOSE_DEBUG(" - Bones"); NextNode(); while (m_currentNodeName == nnBone) { @@ -851,7 +851,7 @@ void OgreXmlSerializer::ReadBones(Skeleton *skeleton) { as per the Ogre skeleton spec. It might be more that other (later) code in this imported does not break. */ for (size_t i = 0, len = skeleton->bones.size(); i < len; ++i) { Bone *b = skeleton->bones[i]; - ASSIMP_LOG_DEBUG_F(" ", b->id, " ", b->name); + ASSIMP_LOG_VERBOSE_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/AssetLib/Ply/PlyParser.cpp b/code/AssetLib/Ply/PlyParser.cpp index d47ca5b6f..1b885fb9c 100644 --- a/code/AssetLib/Ply/PlyParser.cpp +++ b/code/AssetLib/Ply/PlyParser.cpp @@ -514,7 +514,7 @@ bool PLY::DOM::SkipComments(std::vector &buffer) // ------------------------------------------------------------------------------------------------ bool PLY::DOM::ParseHeader(IOStreamBuffer &streamBuffer, std::vector &buffer, bool isBinary) { - ASSIMP_LOG_DEBUG("PLY::DOM::ParseHeader() begin"); + ASSIMP_LOG_VERBOSE_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); - ASSIMP_LOG_DEBUG("PLY::DOM::ParseHeader() succeeded"); + ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseHeader() succeeded"); return true; } // ------------------------------------------------------------------------------------------------ bool PLY::DOM::ParseElementInstanceLists(IOStreamBuffer &streamBuffer, std::vector &buffer, PLYImporter* loader) { - ASSIMP_LOG_DEBUG("PLY::DOM::ParseElementInstanceLists() begin"); + ASSIMP_LOG_VERBOSE_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 } } - ASSIMP_LOG_DEBUG("PLY::DOM::ParseElementInstanceLists() succeeded"); + ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseElementInstanceLists() succeeded"); return true; } @@ -582,7 +582,7 @@ bool PLY::DOM::ParseElementInstanceListsBinary(IOStreamBuffer &streamBuffe PLYImporter* loader, bool p_bBE) { - ASSIMP_LOG_DEBUG("PLY::DOM::ParseElementInstanceListsBinary() begin"); + ASSIMP_LOG_VERBOSE_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 } } - ASSIMP_LOG_DEBUG("PLY::DOM::ParseElementInstanceListsBinary() succeeded"); + ASSIMP_LOG_VERBOSE_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); - ASSIMP_LOG_DEBUG("PLY::DOM::ParseInstanceBinary() begin"); + ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstanceBinary() begin"); if (!p_pcOut->ParseHeader(streamBuffer, buffer, true)) { - ASSIMP_LOG_DEBUG("PLY::DOM::ParseInstanceBinary() failure"); + ASSIMP_LOG_VERBOSE_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)) { - ASSIMP_LOG_DEBUG("PLY::DOM::ParseInstanceBinary() failure"); + ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstanceBinary() failure"); return false; } - ASSIMP_LOG_DEBUG("PLY::DOM::ParseInstanceBinary() succeeded"); + ASSIMP_LOG_VERBOSE_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); - ASSIMP_LOG_DEBUG("PLY::DOM::ParseInstance() begin"); + ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstance() begin"); if (!p_pcOut->ParseHeader(streamBuffer, buffer, false)) { - ASSIMP_LOG_DEBUG("PLY::DOM::ParseInstance() failure"); + ASSIMP_LOG_VERBOSE_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)) { - ASSIMP_LOG_DEBUG("PLY::DOM::ParseInstance() failure"); + ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstance() failure"); return false; } - ASSIMP_LOG_DEBUG("PLY::DOM::ParseInstance() succeeded"); + ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseInstance() succeeded"); return true; } diff --git a/code/PostProcessing/TriangulateProcess.cpp b/code/PostProcessing/TriangulateProcess.cpp index 3fd7eea21..cd9be0d21 100644 --- a/code/PostProcessing/TriangulateProcess.cpp +++ b/code/PostProcessing/TriangulateProcess.cpp @@ -490,7 +490,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) // drop dumb 0-area triangles - deactivated for now: //FindDegenerates post processing step can do the same thing //if (std::fabs(GetArea2D(temp_verts[i[0]],temp_verts[i[1]],temp_verts[i[2]])) < 1e-5f) { - // ASSIMP_LOG_DEBUG("Dropping triangle with area 0"); + // ASSIMP_LOG_VERBOSE_DEBUG("Dropping triangle with area 0"); // --curOut; // delete[] f->mIndices; From df2630d0e889393ce9a3f3bc202639cf14064cfa Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Mon, 18 May 2020 11:45:13 +0100 Subject: [PATCH 12/21] Change in comment. --- include/assimp/LineSplitter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/assimp/LineSplitter.h b/include/assimp/LineSplitter.h index 869585d92..6dfeac7eb 100644 --- a/include/assimp/LineSplitter.h +++ b/include/assimp/LineSplitter.h @@ -72,7 +72,7 @@ for(LineSplitter splitter(stream);splitter;++splitter) { if (strtol(splitter[2]) > 5) { .. } } - ASSIMP_LOG_DEBUG_F("Current line is: ", splitter.get_index()); + ASSIMP_LOG_VERBOSE_DEBUG_F("Current line is: ", splitter.get_index()); } @endcode */ From 14692368d5e8541cf748008694561ca35074060e Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Mon, 18 May 2020 11:55:14 +0100 Subject: [PATCH 13/21] Same for LogDebug -> LogVerboseDebug --- code/AssetLib/FBX/FBXConverter.cpp | 2 +- code/AssetLib/IFC/IFCBoolean.cpp | 6 +++--- code/AssetLib/IFC/IFCCurve.cpp | 2 +- code/AssetLib/IFC/IFCGeometry.cpp | 6 +++--- code/AssetLib/IFC/IFCLoader.cpp | 8 ++++---- code/AssetLib/IFC/IFCOpenings.cpp | 2 +- code/AssetLib/IFC/IFCUtil.cpp | 4 ++-- include/assimp/LogAux.h | 12 ++++++++++++ 8 files changed, 27 insertions(+), 15 deletions(-) diff --git a/code/AssetLib/FBX/FBXConverter.cpp b/code/AssetLib/FBX/FBXConverter.cpp index fff617683..eb995f429 100644 --- a/code/AssetLib/FBX/FBXConverter.cpp +++ b/code/AssetLib/FBX/FBXConverter.cpp @@ -2719,7 +2719,7 @@ void FBXConverter::GenerateNodeAnimations(std::vector &node_anims, if (doc.Settings().optimizeEmptyAnimationCurves && IsRedundantAnimationData(target, comp, (chain[i]->second))) { - FBXImporter::LogDebug("dropping redundant animation channel for node " + target.Name()); + FBXImporter::LogVerboseDebug("dropping redundant animation channel for node " + target.Name()); continue; } diff --git a/code/AssetLib/IFC/IFCBoolean.cpp b/code/AssetLib/IFC/IFCBoolean.cpp index 2c9f6cf8f..22fbaa01d 100644 --- a/code/AssetLib/IFC/IFCBoolean.cpp +++ b/code/AssetLib/IFC/IFCBoolean.cpp @@ -221,7 +221,7 @@ void ProcessBooleanHalfSpaceDifference(const Schema_2x3::IfcHalfSpaceSolid *hs, result.mVerts.pop_back(); } } - IFCImporter::LogDebug("generating CSG geometry by plane clipping (IfcBooleanClippingResult)"); + IFCImporter::LogVerboseDebug("generating CSG geometry by plane clipping (IfcBooleanClippingResult)"); } // ------------------------------------------------------------------------------------------------ @@ -658,7 +658,7 @@ void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const Schema_2x3::IfcPoly } } } - IFCImporter::LogDebug("generating CSG geometry by plane clipping with polygonal bounding (IfcBooleanClippingResult)"); + IFCImporter::LogVerboseDebug("generating CSG geometry by plane clipping with polygonal bounding (IfcBooleanClippingResult)"); } // ------------------------------------------------------------------------------------------------ @@ -706,7 +706,7 @@ void ProcessBooleanExtrudedAreaSolidDifference(const Schema_2x3::IfcExtrudedArea vit += pcount; } - IFCImporter::LogDebug("generating CSG geometry by geometric difference to a solid (IfcExtrudedAreaSolid)"); + IFCImporter::LogVerboseDebug("generating CSG geometry by geometric difference to a solid (IfcExtrudedAreaSolid)"); } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/IFC/IFCCurve.cpp b/code/AssetLib/IFC/IFCCurve.cpp index ba2b1eaf1..4643574a8 100644 --- a/code/AssetLib/IFC/IFCCurve.cpp +++ b/code/AssetLib/IFC/IFCCurve.cpp @@ -223,7 +223,7 @@ public: } if ( (std::string)curveSegment.Transition != "CONTINUOUS" ) { - IFCImporter::LogDebug("ignoring transition code on composite curve segment, only continuous transitions are supported"); + IFCImporter::LogVerboseDebug("ignoring transition code on composite curve segment, only continuous transitions are supported"); } curves.push_back( CurveEntry(bc,IsTrue(curveSegment.SameSense)) ); diff --git a/code/AssetLib/IFC/IFCGeometry.cpp b/code/AssetLib/IFC/IFCGeometry.cpp index 781f01964..f996c8753 100644 --- a/code/AssetLib/IFC/IFCGeometry.cpp +++ b/code/AssetLib/IFC/IFCGeometry.cpp @@ -319,7 +319,7 @@ void ProcessRevolvedAreaSolid(const Schema_2x3::IfcRevolvedAreaSolid& solid, Tem ConvertAxisPlacement(trafo, solid.Position); result.Transform(trafo); - IFCImporter::LogDebug("generate mesh procedurally by radial extrusion (IfcRevolvedAreaSolid)"); + IFCImporter::LogVerboseDebug("generate mesh procedurally by radial extrusion (IfcRevolvedAreaSolid)"); } // ------------------------------------------------------------------------------------------------ @@ -457,7 +457,7 @@ void ProcessSweptDiskSolid(const Schema_2x3::IfcSweptDiskSolid &solid, TempMesh& } } - IFCImporter::LogDebug("generate mesh procedurally by sweeping a disk along a curve (IfcSweptDiskSolid)"); + IFCImporter::LogVerboseDebug("generate mesh procedurally by sweeping a disk along a curve (IfcSweptDiskSolid)"); } // ------------------------------------------------------------------------------------------------ @@ -660,7 +660,7 @@ void ProcessExtrudedArea(const Schema_2x3::IfcExtrudedAreaSolid& solid, const Te IFCImporter::LogWarn("failed to resolve all openings, presumably their topology is not supported by Assimp"); } - IFCImporter::LogDebug("generate mesh procedurally by extrusion (IfcExtrudedAreaSolid)"); + IFCImporter::LogVerboseDebug("generate mesh procedurally by extrusion (IfcExtrudedAreaSolid)"); // If this is an opening element, store both the extruded mesh and the 2D profile mesh // it was created from. Return an empty mesh to the caller. diff --git a/code/AssetLib/IFC/IFCLoader.cpp b/code/AssetLib/IFC/IFCLoader.cpp index b96733c68..9ec377d21 100644 --- a/code/AssetLib/IFC/IFCLoader.cpp +++ b/code/AssetLib/IFC/IFCLoader.cpp @@ -641,14 +641,14 @@ aiNode *ProcessSpatialStructure(aiNode *parent, const Schema_2x3::IfcProduct &el bool skipGeometry = false; if (conv.settings.skipSpaceRepresentations) { if (el.ToPtr()) { - IFCImporter::LogDebug("skipping IfcSpace entity due to importer settings"); + IFCImporter::LogVerboseDebug("skipping IfcSpace entity due to importer settings"); skipGeometry = true; } } if (conv.settings.skipAnnotations) { if (el.ToPtr()) { - IFCImporter::LogDebug("skipping IfcAnnotation entity due to importer settings"); + IFCImporter::LogVerboseDebug("skipping IfcAnnotation entity due to importer settings"); return nullptr; } } @@ -856,7 +856,7 @@ void ProcessSpatialStructures(ConversionData &conv) { if (!prod) { continue; } - IFCImporter::LogDebug("looking at spatial structure `" + (prod->Name ? prod->Name.Get() : "unnamed") + "`" + (prod->ObjectType ? " which is of type " + prod->ObjectType.Get() : "")); + IFCImporter::LogVerboseDebug("looking at spatial structure `" + (prod->Name ? prod->Name.Get() : "unnamed") + "`" + (prod->ObjectType ? " which is of type " + prod->ObjectType.Get() : "")); // the primary sites are referenced by an IFCRELAGGREGATES element which assigns them to the IFCPRODUCT const STEP::DB::RefMap &refs = conv.db.GetRefs(); @@ -868,7 +868,7 @@ void ProcessSpatialStructures(ConversionData &conv) { // comparing pointer values is not sufficient, we would need to cast them to the same type first // as there is multiple inheritance in the game. if (def.GetID() == prod->GetID()) { - IFCImporter::LogDebug("selecting this spatial structure as root structure"); + IFCImporter::LogVerboseDebug("selecting this spatial structure as root structure"); // got it, this is one primary site. nodes.push_back(ProcessSpatialStructure(NULL, *prod, conv, NULL)); } diff --git a/code/AssetLib/IFC/IFCOpenings.cpp b/code/AssetLib/IFC/IFCOpenings.cpp index f77f33faf..e15691957 100644 --- a/code/AssetLib/IFC/IFCOpenings.cpp +++ b/code/AssetLib/IFC/IFCOpenings.cpp @@ -1359,7 +1359,7 @@ bool GenerateOpenings(std::vector& openings, break; } else { - IFCImporter::LogDebug("merging overlapping openings"); + IFCImporter::LogVerboseDebug("merging overlapping openings"); ExtractVerticesFromClipper(poly[0].outer, temp_contour, false); // Generate the union of the bounding boxes diff --git a/code/AssetLib/IFC/IFCUtil.cpp b/code/AssetLib/IFC/IFCUtil.cpp index 2620160df..e7c04bd89 100644 --- a/code/AssetLib/IFC/IFCUtil.cpp +++ b/code/AssetLib/IFC/IFCUtil.cpp @@ -162,7 +162,7 @@ void TempMesh::RemoveDegenerates() } if(drop) { - IFCImporter::LogDebug("removing degenerate faces"); + IFCImporter::LogVerboseDebug("removing degenerate faces"); } } @@ -437,7 +437,7 @@ void TempMesh::RemoveAdjacentDuplicates() { base += cnt; } if(drop) { - IFCImporter::LogDebug("removing duplicate vertices"); + IFCImporter::LogVerboseDebug("removing duplicate vertices"); } } diff --git a/include/assimp/LogAux.h b/include/assimp/LogAux.h index 2265ff19c..330c5e93e 100644 --- a/include/assimp/LogAux.h +++ b/include/assimp/LogAux.h @@ -94,6 +94,12 @@ public: } } + static void LogVerboseDebug(const Formatter::format& message) { + if (!DefaultLogger::isNullLogger()) { + ASSIMP_LOG_VERBOSE_DEBUG(Prefix()+(std::string)message); + } + } + // https://sourceforge.net/tracker/?func=detail&atid=1067632&aid=3358562&group_id=226462 #if !defined(__GNUC__) || !defined(__APPLE__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) @@ -125,6 +131,12 @@ public: } } + // ------------------------------------------------------------------------------------------------ + static void LogVerboseDebug (const char* message) { + if (!DefaultLogger::isNullLogger()) { + LogVerboseDebug(Formatter::format(message)); + } + } #endif private: From e9a3cc2c8a2806ceee2124ea0664c75f92b3933f Mon Sep 17 00:00:00 2001 From: Kevin Shepherd Date: Mon, 18 May 2020 16:07:46 +0100 Subject: [PATCH 14/21] Fixed rotation order bug in BVH Loader This bug has been present since after the 4.10 release. It fixes the issue "play the bvh error" #2187 Almost all bvh files are affected, such as any of the CMU library. The bug is caused by the introduction of channelMap in the BVHLoader.cpp - function void BVHLoader::CreateAnimation(aiScene *pScene). The channelMap loses the rotation order present oin the BVH file, and always applies the rotations in X,Y,Z order. --- code/AssetLib/BVH/BVHLoader.cpp | 51 ++++++++++++++------------------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/code/AssetLib/BVH/BVHLoader.cpp b/code/AssetLib/BVH/BVHLoader.cpp index 9c22879d2..348c30337 100644 --- a/code/AssetLib/BVH/BVHLoader.cpp +++ b/code/AssetLib/BVH/BVHLoader.cpp @@ -493,37 +493,30 @@ void BVHLoader::CreateAnimation(aiScene *pScene) { for (unsigned int fr = 0; fr < mAnimNumFrames; ++fr) { aiMatrix4x4 temp; aiMatrix3x3 rotMatrix; - for (BVHLoader::ChannelType channel = Channel_RotationX; channel <= Channel_RotationZ; channel = (BVHLoader::ChannelType)(channel + 1)) { - //Find channel in node - std::map::iterator mapIter = channelMap.find(channel); - - if (mapIter == channelMap.end()) - throw DeadlyImportError("Missing rotation channel in node " + nodeName); - else { - int channelIdx = mapIter->second; - // translate ZXY euler angels into a quaternion + for (unsigned int channelIdx = 0; channelIdx < node.mChannels.size(); ++ channelIdx) { + switch (node.mChannels[channelIdx]) { + case Channel_RotationX: + { const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f; - - // Compute rotation transformations in the right order - switch (channel) { - case Channel_RotationX: - aiMatrix4x4::RotationX(angle, temp); - rotMatrix *= aiMatrix3x3(temp); - break; - case Channel_RotationY: - aiMatrix4x4::RotationY(angle, temp); - rotMatrix *= aiMatrix3x3(temp); - break; - case Channel_RotationZ: - aiMatrix4x4::RotationZ(angle, temp); - rotMatrix *= aiMatrix3x3(temp); - break; - default: - break; + aiMatrix4x4::RotationX( angle, temp); rotMatrix *= aiMatrix3x3( temp); } - } - } - + break; + case Channel_RotationY: + { + const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f; + aiMatrix4x4::RotationY( angle, temp); rotMatrix *= aiMatrix3x3( temp); + } + break; + case Channel_RotationZ: + { + const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f; + aiMatrix4x4::RotationZ( angle, temp); rotMatrix *= aiMatrix3x3( temp); + } + break; + default: + break; + } + } rotkey->mTime = double(fr); rotkey->mValue = aiQuaternion(rotMatrix); ++rotkey; From 0897c4c7be31880e36f6bac249698b1dc4fc5b2f Mon Sep 17 00:00:00 2001 From: Yingying Wang Date: Mon, 18 May 2020 11:31:44 -0700 Subject: [PATCH 15/21] merge --- code/AssetLib/glTF2/glTF2Asset.h | 10 ++++-- code/AssetLib/glTF2/glTF2Asset.inl | 55 ++++++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index 9fc85c548..0d3b5d8b8 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -1,4 +1,4 @@ -/* +/* Open Asset Import Library (assimp) ---------------------------------------------------------------------- @@ -370,7 +370,8 @@ struct Object { //! An accessor provides a typed view into a BufferView or a subset of a BufferView //! similar to how WebGL's vertexAttribPointer() defines an attribute in a buffer. struct Accessor : public Object { - struct Sparse; + struct Sparse; //wangyi 0506 + Ref bufferView; //!< The ID of the bufferView. (required) size_t byteOffset; //!< The offset relative to the start of the bufferView in bytes. (required) ComponentType componentType; //!< The datatype of components in the attribute. (required) @@ -378,7 +379,7 @@ struct Accessor : public Object { AttribType::Value type; //!< Specifies if the attribute is a scalar, vector, or matrix. (required) std::vector max; //!< Maximum value of each component in this attribute. std::vector min; //!< Minimum value of each component in this attribute. - std::unique_ptr sparse; + std::unique_ptr sparse; //wangyi 0506 unsigned int GetNumComponents(); unsigned int GetBytesPerComponent(); @@ -390,6 +391,7 @@ struct Accessor : public Object { void ExtractData(T *&outData); void WriteData(size_t count, const void *src_buffer, size_t src_stride); + //wangyi 0506 void WriteSparseValues(size_t count, const void *src_data, size_t src_dataStride); void WriteSparseIndices(size_t count, const void *src_idx, size_t src_idxStride); @@ -430,6 +432,7 @@ struct Accessor : public Object { Accessor() {} void Read(Value &obj, Asset &r); + //wangyi 0506 //sparse struct Sparse { size_t count; @@ -580,6 +583,7 @@ struct BufferView : public Object { BufferViewTarget target; //! The target that the WebGL buffer should be bound to. void Read(Value &obj, Asset &r); + //wangyi 0506 uint8_t *GetPointer(size_t accOffset); }; diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index 75ff0b6fc..29d745234 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -1,22 +1,30 @@ /* Open Asset Import Library (assimp) ---------------------------------------------------------------------- + Copyright (c) 2006-2020, assimp team + + All rights reserved. + Redistribution and use of this software in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the name of the assimp team, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission of the assimp team. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -28,6 +36,7 @@ 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. + ---------------------------------------------------------------------- */ @@ -547,6 +556,7 @@ inline void BufferView::Read(Value &obj, Asset &r) { byteStride = MemberOrDefault(obj, "byteStride", 0u); } +//wangyi 0506 inline uint8_t *BufferView::GetPointer(size_t accOffset) { if (!buffer) return 0; uint8_t *basePtr = buffer->GetPointer(); @@ -566,7 +576,7 @@ inline uint8_t *BufferView::GetPointer(size_t accOffset) { // // struct Accessor // - +//wangyi 0506 inline void Accessor::Sparse::PopulateData(size_t numBytes, uint8_t *bytes) { if (bytes) { data.assign(bytes, bytes + numBytes); @@ -605,7 +615,22 @@ inline void Accessor::Sparse::PatchData(unsigned int elementSize) { pIndices += indexSize; } } +/* old +inline void Accessor::Read(Value &obj, Asset &r) { + if (Value *bufferViewVal = FindUInt(obj, "bufferView")) { + bufferView = r.bufferViews.Retrieve(bufferViewVal->GetUint()); + } + + byteOffset = MemberOrDefault(obj, "byteOffset", size_t(0)); + componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE); + count = MemberOrDefault(obj, "count", size_t(0)); + + const char *typestr; + type = ReadMember(obj, "type", typestr) ? AttribType::FromString(typestr) : AttribType::SCALAR; +}*/ + +// wangyi 0506 inline void Accessor::Read(Value &obj, Asset &r) { if (Value *bufferViewVal = FindUInt(obj, "bufferView")) { @@ -619,6 +644,7 @@ inline void Accessor::Read(Value &obj, Asset &r) { const char *typestr; type = ReadMember(obj, "type", typestr) ? AttribType::FromString(typestr) : AttribType::SCALAR; + //wangyi 0506 if (Value *sparseValue = FindObject(obj, "sparse")) { sparse.reset(new Sparse); // count @@ -668,6 +694,27 @@ inline unsigned int Accessor::GetElementSize() { return GetNumComponents() * GetBytesPerComponent(); } +/* +inline uint8_t *Accessor::GetPointer() { + if (!bufferView || !bufferView->buffer) return 0; + uint8_t *basePtr = bufferView->buffer->GetPointer(); + if (!basePtr) return 0; + + size_t offset = byteOffset + bufferView->byteOffset; + + // Check if region is encoded. + if (bufferView->buffer->EncodedRegion_Current != nullptr) { + const size_t begin = bufferView->buffer->EncodedRegion_Current->Offset; + const size_t end = begin + bufferView->buffer->EncodedRegion_Current->DecodedData_Length; + + if ((offset >= begin) && (offset < end)) + return &bufferView->buffer->EncodedRegion_Current->DecodedData[offset - begin]; + } + + return basePtr + offset; +}*/ + +// wangyi 0506 inline uint8_t *Accessor::GetPointer() { if (sparse) return sparse->data.data(); @@ -724,6 +771,8 @@ void Accessor::ExtractData(T *&outData) { const size_t targetElemSize = sizeof(T); ai_assert(elemSize <= targetElemSize); + + //wangyi 0506 ai_assert(count * stride <= (bufferView ? bufferView->byteLength : sparse->data.size())); outData = new T[count]; @@ -749,6 +798,7 @@ inline void Accessor::WriteData(size_t _count, const void *src_buffer, size_t sr CopyData(_count, src, src_stride, dst, dst_stride); } +//wangyi 0506 inline void Accessor::WriteSparseValues(size_t _count, const void *src_data, size_t src_dataStride) { if (!sparse) return; @@ -763,6 +813,7 @@ inline void Accessor::WriteSparseValues(size_t _count, const void *src_data, siz CopyData(_count, value_src, src_dataStride, value_dst, value_dst_stride); } +//wangyi 0506 inline void Accessor::WriteSparseIndices(size_t _count, const void *src_idx, size_t src_idxStride) { if (!sparse) return; @@ -1673,4 +1724,4 @@ inline std::string Asset::FindUniqueID(const std::string &str, const char *suffi #pragma warning(pop) #endif // _WIN32 -} // namespace glTF2 \ No newline at end of file +} // namespace glTF2 From e39c6328097ce3cd8ff7c872f62611aac6c8009f Mon Sep 17 00:00:00 2001 From: Yingying Wang Date: Mon, 18 May 2020 11:50:51 -0700 Subject: [PATCH 16/21] cleanup --- code/AssetLib/glTF2/glTF2Asset.h | 9 +--- code/AssetLib/glTF2/glTF2Asset.inl | 70 ------------------------------ 2 files changed, 2 insertions(+), 77 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index 0d3b5d8b8..99bcaf072 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -370,7 +370,7 @@ struct Object { //! An accessor provides a typed view into a BufferView or a subset of a BufferView //! similar to how WebGL's vertexAttribPointer() defines an attribute in a buffer. struct Accessor : public Object { - struct Sparse; //wangyi 0506 + struct Sparse; Ref bufferView; //!< The ID of the bufferView. (required) size_t byteOffset; //!< The offset relative to the start of the bufferView in bytes. (required) @@ -379,7 +379,7 @@ struct Accessor : public Object { AttribType::Value type; //!< Specifies if the attribute is a scalar, vector, or matrix. (required) std::vector max; //!< Maximum value of each component in this attribute. std::vector min; //!< Minimum value of each component in this attribute. - std::unique_ptr sparse; //wangyi 0506 + std::unique_ptr sparse; unsigned int GetNumComponents(); unsigned int GetBytesPerComponent(); @@ -391,9 +391,6 @@ struct Accessor : public Object { void ExtractData(T *&outData); void WriteData(size_t count, const void *src_buffer, size_t src_stride); - //wangyi 0506 - void WriteSparseValues(size_t count, const void *src_data, size_t src_dataStride); - void WriteSparseIndices(size_t count, const void *src_idx, size_t src_idxStride); //! Helper class to iterate the data class Indexer { @@ -432,7 +429,6 @@ struct Accessor : public Object { Accessor() {} void Read(Value &obj, Asset &r); - //wangyi 0506 //sparse struct Sparse { size_t count; @@ -583,7 +579,6 @@ struct BufferView : public Object { BufferViewTarget target; //! The target that the WebGL buffer should be bound to. void Read(Value &obj, Asset &r); - //wangyi 0506 uint8_t *GetPointer(size_t accOffset); }; diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index 29d745234..9f852ebf8 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -556,7 +556,6 @@ inline void BufferView::Read(Value &obj, Asset &r) { byteStride = MemberOrDefault(obj, "byteStride", 0u); } -//wangyi 0506 inline uint8_t *BufferView::GetPointer(size_t accOffset) { if (!buffer) return 0; uint8_t *basePtr = buffer->GetPointer(); @@ -576,7 +575,6 @@ inline uint8_t *BufferView::GetPointer(size_t accOffset) { // // struct Accessor // -//wangyi 0506 inline void Accessor::Sparse::PopulateData(size_t numBytes, uint8_t *bytes) { if (bytes) { data.assign(bytes, bytes + numBytes); @@ -615,22 +613,7 @@ inline void Accessor::Sparse::PatchData(unsigned int elementSize) { pIndices += indexSize; } } -/* old -inline void Accessor::Read(Value &obj, Asset &r) { - if (Value *bufferViewVal = FindUInt(obj, "bufferView")) { - bufferView = r.bufferViews.Retrieve(bufferViewVal->GetUint()); - } - - byteOffset = MemberOrDefault(obj, "byteOffset", size_t(0)); - componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE); - count = MemberOrDefault(obj, "count", size_t(0)); - - const char *typestr; - type = ReadMember(obj, "type", typestr) ? AttribType::FromString(typestr) : AttribType::SCALAR; -}*/ - -// wangyi 0506 inline void Accessor::Read(Value &obj, Asset &r) { if (Value *bufferViewVal = FindUInt(obj, "bufferView")) { @@ -644,7 +627,6 @@ inline void Accessor::Read(Value &obj, Asset &r) { const char *typestr; type = ReadMember(obj, "type", typestr) ? AttribType::FromString(typestr) : AttribType::SCALAR; - //wangyi 0506 if (Value *sparseValue = FindObject(obj, "sparse")) { sparse.reset(new Sparse); // count @@ -694,27 +676,6 @@ inline unsigned int Accessor::GetElementSize() { return GetNumComponents() * GetBytesPerComponent(); } -/* -inline uint8_t *Accessor::GetPointer() { - if (!bufferView || !bufferView->buffer) return 0; - uint8_t *basePtr = bufferView->buffer->GetPointer(); - if (!basePtr) return 0; - - size_t offset = byteOffset + bufferView->byteOffset; - - // Check if region is encoded. - if (bufferView->buffer->EncodedRegion_Current != nullptr) { - const size_t begin = bufferView->buffer->EncodedRegion_Current->Offset; - const size_t end = begin + bufferView->buffer->EncodedRegion_Current->DecodedData_Length; - - if ((offset >= begin) && (offset < end)) - return &bufferView->buffer->EncodedRegion_Current->DecodedData[offset - begin]; - } - - return basePtr + offset; -}*/ - -// wangyi 0506 inline uint8_t *Accessor::GetPointer() { if (sparse) return sparse->data.data(); @@ -771,8 +732,6 @@ void Accessor::ExtractData(T *&outData) { const size_t targetElemSize = sizeof(T); ai_assert(elemSize <= targetElemSize); - - //wangyi 0506 ai_assert(count * stride <= (bufferView ? bufferView->byteLength : sparse->data.size())); outData = new T[count]; @@ -798,35 +757,6 @@ inline void Accessor::WriteData(size_t _count, const void *src_buffer, size_t sr CopyData(_count, src, src_stride, dst, dst_stride); } -//wangyi 0506 -inline void Accessor::WriteSparseValues(size_t _count, const void *src_data, size_t src_dataStride) { - if (!sparse) - return; - - // values - uint8_t *value_buffer_ptr = sparse->values->buffer->GetPointer(); - size_t value_offset = sparse->valuesByteOffset + sparse->values->byteOffset; - size_t value_dst_stride = GetNumComponents() * GetBytesPerComponent(); - const uint8_t *value_src = reinterpret_cast(src_data); - uint8_t *value_dst = reinterpret_cast(value_buffer_ptr + value_offset); - ai_assert(value_dst + _count * value_dst_stride <= value_buffer_ptr + sparse->values->buffer->byteLength); - CopyData(_count, value_src, src_dataStride, value_dst, value_dst_stride); -} - -//wangyi 0506 -inline void Accessor::WriteSparseIndices(size_t _count, const void *src_idx, size_t src_idxStride) { - if (!sparse) - return; - - // indices - uint8_t *indices_buffer_ptr = sparse->indices->buffer->GetPointer(); - size_t indices_offset = sparse->indicesByteOffset + sparse->indices->byteOffset; - size_t indices_dst_stride = 1 * sizeof(unsigned short); - const uint8_t *indices_src = reinterpret_cast(src_idx); - uint8_t *indices_dst = reinterpret_cast(indices_buffer_ptr + indices_offset); - ai_assert(indices_dst + _count * indices_dst_stride <= indices_buffer_ptr + sparse->indices->buffer->byteLength); - CopyData(_count, indices_src, src_idxStride, indices_dst, indices_dst_stride); -} inline Accessor::Indexer::Indexer(Accessor &acc) : accessor(acc), data(acc.GetPointer()), From 193deb34411264227787774cf351ea73d03eafd6 Mon Sep 17 00:00:00 2001 From: Yingying Wang Date: Mon, 18 May 2020 12:01:09 -0700 Subject: [PATCH 17/21] cleanup --- code/AssetLib/glTF2/glTF2Asset.inl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index 9f852ebf8..328c57e38 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -1169,10 +1169,10 @@ inline void Camera::Read(Value &obj, Asset & /*r*/) { cameraProperties.perspective.zfar = MemberOrDefault(*it, "zfar", 100.f); cameraProperties.perspective.znear = MemberOrDefault(*it, "znear", 0.01f); } else { - cameraProperties.ortographic.xmag = MemberOrDefault(obj, "xmag", 1.f); - cameraProperties.ortographic.ymag = MemberOrDefault(obj, "ymag", 1.f); - cameraProperties.ortographic.zfar = MemberOrDefault(obj, "zfar", 100.f); - cameraProperties.ortographic.znear = MemberOrDefault(obj, "znear", 0.01f); + cameraProperties.ortographic.xmag = MemberOrDefault(*it, "xmag", 1.f); + cameraProperties.ortographic.ymag = MemberOrDefault(*it, "ymag", 1.f); + cameraProperties.ortographic.zfar = MemberOrDefault(*it, "zfar", 100.f); + cameraProperties.ortographic.znear = MemberOrDefault(*it, "znear", 0.01f); } } @@ -1248,7 +1248,7 @@ inline void Node::Read(Value &obj, Asset &r) { Value *curSkin = FindUInt(obj, "skin"); if (nullptr != curSkin) { - this->skin = r.skins.Retrieve(curSkin->GetUint()); + this->skin = r.skins.Get(curSkin->GetUint()); } Value *curCamera = FindUInt(obj, "camera"); @@ -1539,7 +1539,7 @@ inline void Asset::Load(const std::string &pFile, bool isBinary) { } } - // Force reading of skins since they're not always directly referenced + // Read skins after nodes have been loaded to avoid infinite recursion if (Value *skinsArray = FindArray(doc, "skins")) { for (unsigned int i = 0; i < skinsArray->Size(); ++i) { skins.Retrieve(i); From c4055d04b4c960b6db02c587f9c87744052294dc Mon Sep 17 00:00:00 2001 From: Ryan Styrczula Date: Tue, 19 May 2020 14:38:10 -0400 Subject: [PATCH 18/21] Fix double free caused in FindInvalidDataProcess In debug builds, there's no issues, but in release, an invalid mesh that is deleted in FindInvalidDataProcess will be double free'd when the parent scene is destroyed. --- code/PostProcessing/FindInvalidDataProcess.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/PostProcessing/FindInvalidDataProcess.cpp b/code/PostProcessing/FindInvalidDataProcess.cpp index 99be52fa4..3ad2446b3 100644 --- a/code/PostProcessing/FindInvalidDataProcess.cpp +++ b/code/PostProcessing/FindInvalidDataProcess.cpp @@ -124,7 +124,7 @@ void FindInvalidDataProcess::Execute(aiScene *pScene) { if (2 == result) { // remove this mesh delete pScene->mMeshes[a]; - AI_DEBUG_INVALIDATE_PTR(pScene->mMeshes[a]); + pScene->mMeshes[a] = NULL; meshMapping[a] = UINT_MAX; continue; From e33ed9e7a1b3307683a105b5821c6c8fd2e2252c Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 25 May 2020 20:30:18 +0200 Subject: [PATCH 19/21] File is duplicated closes https://github.com/assimp/assimp/issues/3238 --- code/Collada/ColladaExporter.cpp | 1704 ------------------------------ 1 file changed, 1704 deletions(-) delete mode 100644 code/Collada/ColladaExporter.cpp diff --git a/code/Collada/ColladaExporter.cpp b/code/Collada/ColladaExporter.cpp deleted file mode 100644 index 05df6fc94..000000000 --- a/code/Collada/ColladaExporter.cpp +++ /dev/null @@ -1,1704 +0,0 @@ -/* -Open Asset Import Library (assimp) ----------------------------------------------------------------------- - -Copyright (c) 2006-2020, assimp team - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -*/ - -#ifndef ASSIMP_BUILD_NO_EXPORT -#ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER - -#include "ColladaExporter.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -using namespace Assimp; - -namespace Assimp { - -// ------------------------------------------------------------------------------------------------ -// Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp -void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) { - std::string path = DefaultIOSystem::absolutePath(std::string(pFile)); - std::string file = DefaultIOSystem::completeBaseName(std::string(pFile)); - - // invoke the exporter - ColladaExporter iDoTheExportThing( pScene, pIOSystem, path, file); - - if (iDoTheExportThing.mOutput.fail()) { - throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile)); - } - - // we're still here - export successfully completed. Write result to the given IOSYstem - std::unique_ptr outfile (pIOSystem->Open(pFile,"wt")); - if(outfile == NULL) { - throw DeadlyExportError("could not open output .dae file: " + std::string(pFile)); - } - - // XXX maybe use a small wrapper around IOStream that behaves like std::stringstream in order to avoid the extra copy. - outfile->Write( iDoTheExportThing.mOutput.str().c_str(), static_cast(iDoTheExportThing.mOutput.tellp()),1); -} - -} // end of namespace Assimp - -// ------------------------------------------------------------------------------------------------ -// Encodes a string into a valid XML ID using the xsd:ID schema qualifications. -static const std::string XMLIDEncode(const std::string& name) { - const char XML_ID_CHARS[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-."; - const unsigned int XML_ID_CHARS_COUNT = sizeof(XML_ID_CHARS) / sizeof(char); - - if (name.length() == 0) { - return name; - } - - std::stringstream idEncoded; - - // xsd:ID must start with letter or underscore - if (!((name[0] >= 'A' && name[0] <= 'z') || name[0] == '_')) { - idEncoded << '_'; - } - - for (std::string::const_iterator it = name.begin(); it != name.end(); ++it) { - // xsd:ID can only contain letters, digits, underscores, hyphens and periods - if (strchr(XML_ID_CHARS, *it) != nullptr) { - idEncoded << *it; - } else { - // Select placeholder character based on invalid character to prevent name collisions - idEncoded << XML_ID_CHARS[(*it) % XML_ID_CHARS_COUNT]; - } - } - - return idEncoded.str(); -} - -// ------------------------------------------------------------------------------------------------ -// Constructor for a specific scene to export -ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file) -: mIOSystem(pIOSystem) -, mPath(path) -, mFile(file) { - // make sure that all formatting happens using the standard, C locale and not the user's current locale - mOutput.imbue( std::locale("C") ); - mOutput.precision(ASSIMP_AI_REAL_TEXT_PRECISION); - - mScene = pScene; - mSceneOwned = false; - - // set up strings - endstr = "\n"; - - // start writing the file - WriteFile(); -} - -// ------------------------------------------------------------------------------------------------ -// Destructor -ColladaExporter::~ColladaExporter() { - if ( mSceneOwned ) { - delete mScene; - } -} - -// ------------------------------------------------------------------------------------------------ -// Starts writing the contents -void ColladaExporter::WriteFile() { - // write the DTD - mOutput << "" << endstr; - // COLLADA element start - mOutput << "" << endstr; - PushTag(); - - WriteTextures(); - WriteHeader(); - - WriteCamerasLibrary(); - WriteLightsLibrary(); - WriteMaterials(); - WriteGeometryLibrary(); - WriteControllerLibrary(); - - WriteSceneLibrary(); - - // customized, Writes the animation library - WriteAnimationsLibrary(); - - // useless Collada fu at the end, just in case we haven't had enough indirections, yet. - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "mRootNode->mName.C_Str()) + "\" />" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << "" << endstr; -} - -// ------------------------------------------------------------------------------------------------ -// Writes the asset header -void ColladaExporter::WriteHeader() { - static const ai_real epsilon = Math::getEpsilon(); - static const aiQuaternion x_rot(aiMatrix3x3( - 0, -1, 0, - 1, 0, 0, - 0, 0, 1)); - static const aiQuaternion y_rot(aiMatrix3x3( - 1, 0, 0, - 0, 1, 0, - 0, 0, 1)); - static const aiQuaternion z_rot(aiMatrix3x3( - 1, 0, 0, - 0, 0, 1, - 0, -1, 0)); - - static const unsigned int date_nb_chars = 20; - char date_str[date_nb_chars]; - std::time_t date = std::time(NULL); - std::strftime(date_str, date_nb_chars, "%Y-%m-%dT%H:%M:%S", std::localtime(&date)); - - aiVector3D scaling; - aiQuaternion rotation; - aiVector3D position; - mScene->mRootNode->mTransformation.Decompose(scaling, rotation, position); - rotation.Normalize(); - - bool add_root_node = false; - - ai_real scale = 1.0; - if(std::abs(scaling.x - scaling.y) <= epsilon && std::abs(scaling.x - scaling.z) <= epsilon && std::abs(scaling.y - scaling.z) <= epsilon) { - scale = (ai_real) ((((double) scaling.x) + ((double) scaling.y) + ((double) scaling.z)) / 3.0); - } else { - add_root_node = true; - } - - std::string up_axis = "Y_UP"; - if(rotation.Equal(x_rot, epsilon)) { - up_axis = "X_UP"; - } else if(rotation.Equal(y_rot, epsilon)) { - up_axis = "Y_UP"; - } else if(rotation.Equal(z_rot, epsilon)) { - up_axis = "Z_UP"; - } else { - add_root_node = true; - } - - if(! position.Equal(aiVector3D(0, 0, 0))) { - add_root_node = true; - } - - if(mScene->mRootNode->mNumChildren == 0) { - add_root_node = true; - } - - if(add_root_node) { - aiScene* scene; - SceneCombiner::CopyScene(&scene, mScene); - - aiNode* root = new aiNode("Scene"); - - root->mNumChildren = 1; - root->mChildren = new aiNode*[root->mNumChildren]; - - root->mChildren[0] = scene->mRootNode; - scene->mRootNode->mParent = root; - scene->mRootNode = root; - - mScene = scene; - mSceneOwned = true; - - up_axis = "Y_UP"; - scale = 1.0; - } - - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - - // If no Scene metadata, use root node metadata - aiMetadata* meta = mScene->mMetaData; - if (nullptr == meta) { - meta = mScene->mRootNode->mMetaData; - } - - aiString value; - if (!meta || !meta->Get("Author", value)) { - mOutput << startstr << "" << "Assimp" << "" << endstr; - } else { - mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; - } - - if (nullptr == meta || !meta->Get(AI_METADATA_SOURCE_GENERATOR, value)) { - mOutput << startstr << "" << "Assimp Exporter" << "" << endstr; - } else { - mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; - } - - if (meta) { - if (meta->Get("Comments", value)) { - mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; - } - if (meta->Get(AI_METADATA_SOURCE_COPYRIGHT, value)) { - mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; - } - if (meta->Get("SourceData", value)) { - mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; - } - } - - PopTag(); - mOutput << startstr << "" << endstr; - - if (nullptr == meta || !meta->Get("Created", value)) { - mOutput << startstr << "" << date_str << "" << endstr; - } else { - mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; - } - - // Modified date is always the date saved - mOutput << startstr << "" << date_str << "" << endstr; - - if (meta) { - if (meta->Get("Keywords", value)) { - mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; - } - if (meta->Get("Revision", value)) { - mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; - } - if (meta->Get("Subject", value)) { - mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; - } - if (meta->Get("Title", value)) { - mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; - } - } - - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << up_axis << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; -} - -// ------------------------------------------------------------------------------------------------ -// Write the embedded textures -void ColladaExporter::WriteTextures() { - static const unsigned int buffer_size = 1024; - char str[buffer_size]; - - if (mScene->HasTextures()) { - for(unsigned int i = 0; i < mScene->mNumTextures; i++) { - // It would be great to be able to create a directory in portable standard C++, but it's not the case, - // so we just write the textures in the current directory. - - aiTexture* texture = mScene->mTextures[i]; - if ( nullptr == texture ) { - continue; - } - - ASSIMP_itoa10(str, buffer_size, i + 1); - - std::string name = mFile + "_texture_" + (i < 1000 ? "0" : "") + (i < 100 ? "0" : "") + (i < 10 ? "0" : "") + str + "." + ((const char*) texture->achFormatHint); - - std::unique_ptr outfile(mIOSystem->Open(mPath + mIOSystem->getOsSeparator() + name, "wb")); - if(outfile == NULL) { - throw DeadlyExportError("could not open output texture file: " + mPath + name); - } - - if(texture->mHeight == 0) { - outfile->Write((void*) texture->pcData, texture->mWidth, 1); - } else { - Bitmap::Save(texture, outfile.get()); - } - - outfile->Flush(); - - textures.insert(std::make_pair(i, name)); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Write the embedded textures -void ColladaExporter::WriteCamerasLibrary() { - if(mScene->HasCameras()) { - - mOutput << startstr << "" << endstr; - PushTag(); - - for( size_t a = 0; a < mScene->mNumCameras; ++a) - WriteCamera( a); - - PopTag(); - mOutput << startstr << "" << endstr; - - } -} - -void ColladaExporter::WriteCamera(size_t pIndex){ - - const aiCamera *cam = mScene->mCameras[pIndex]; - const std::string cameraName = XMLEscape(cam->mName.C_Str()); - const std::string cameraId = XMLIDEncode(cam->mName.C_Str()); - - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - //assimp doesn't support the import of orthographic cameras! se we write - //always perspective - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << ""<< - AI_RAD_TO_DEG(cam->mHorizontalFOV) - <<"" << endstr; - mOutput << startstr << "" - << cam->mAspect - << "" << endstr; - mOutput << startstr << "" - << cam->mClipPlaneNear - << "" << endstr; - mOutput << startstr << "" - << cam->mClipPlaneFar - << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - -} - - -// ------------------------------------------------------------------------------------------------ -// Write the embedded textures -void ColladaExporter::WriteLightsLibrary() { - if(mScene->HasLights()) { - - mOutput << startstr << "" << endstr; - PushTag(); - - for( size_t a = 0; a < mScene->mNumLights; ++a) - WriteLight( a); - - PopTag(); - mOutput << startstr << "" << endstr; - - } -} - -void ColladaExporter::WriteLight(size_t pIndex){ - - const aiLight *light = mScene->mLights[pIndex]; - const std::string lightName = XMLEscape(light->mName.C_Str()); - const std::string lightId = XMLIDEncode(light->mName.C_Str()); - - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - switch(light->mType){ - case aiLightSource_AMBIENT: - WriteAmbienttLight(light); - break; - case aiLightSource_DIRECTIONAL: - WriteDirectionalLight(light); - break; - case aiLightSource_POINT: - WritePointLight(light); - break; - case aiLightSource_SPOT: - WriteSpotLight(light); - break; - case aiLightSource_AREA: - case aiLightSource_UNDEFINED: - case _aiLightSource_Force32Bit: - break; - } - PopTag(); - mOutput << startstr << "" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - -} - -void ColladaExporter::WritePointLight(const aiLight *const light){ - const aiColor3D &color= light->mColorDiffuse; - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" - << color.r<<" "<" << endstr; - mOutput << startstr << "" - << light->mAttenuationConstant - <<"" << endstr; - mOutput << startstr << "" - << light->mAttenuationLinear - <<"" << endstr; - mOutput << startstr << "" - << light->mAttenuationQuadratic - <<"" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - -} - -void ColladaExporter::WriteDirectionalLight(const aiLight *const light){ - const aiColor3D &color= light->mColorDiffuse; - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" - << color.r<<" "<" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - -} - -void ColladaExporter::WriteSpotLight(const aiLight *const light){ - - const aiColor3D &color= light->mColorDiffuse; - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" - << color.r<<" "<" << endstr; - mOutput << startstr << "" - << light->mAttenuationConstant - <<"" << endstr; - mOutput << startstr << "" - << light->mAttenuationLinear - <<"" << endstr; - mOutput << startstr << "" - << light->mAttenuationQuadratic - <<"" << endstr; - - const ai_real fallOffAngle = AI_RAD_TO_DEG(light->mAngleInnerCone); - mOutput << startstr <<"" - << fallOffAngle - <<"" << endstr; - double temp = light->mAngleOuterCone-light->mAngleInnerCone; - - temp = std::cos(temp); - temp = std::log(temp)/std::log(0.1); - temp = 1/temp; - mOutput << startstr << "" - << temp - <<"" << endstr; - - - PopTag(); - mOutput << startstr << "" << endstr; - -} - -void ColladaExporter::WriteAmbienttLight(const aiLight *const light){ - - const aiColor3D &color= light->mColorAmbient; - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" - << color.r<<" "<" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; -} - -// ------------------------------------------------------------------------------------------------ -// Reads a single surface entry from the given material keys -void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial* pSrcMat, - aiTextureType pTexture, const char* pKey, size_t pType, size_t pIndex) { - if( pSrcMat->GetTextureCount( pTexture) > 0 ) { - aiString texfile; - unsigned int uvChannel = 0; - pSrcMat->GetTexture( pTexture, 0, &texfile, NULL, &uvChannel); - - std::string index_str(texfile.C_Str()); - - if(index_str.size() != 0 && index_str[0] == '*') { - unsigned int index; - - index_str = index_str.substr(1, std::string::npos); - - try { - index = (unsigned int) strtoul10_64(index_str.c_str()); - } catch(std::exception& error) { - throw DeadlyExportError(error.what()); - } - - std::map::const_iterator name = textures.find(index); - - if(name != textures.end()) { - poSurface.texture = name->second; - } else { - throw DeadlyExportError("could not find embedded texture at index " + index_str); - } - } else { - poSurface.texture = texfile.C_Str(); - } - - poSurface.channel = uvChannel; - poSurface.exist = true; - } else { - if( pKey ) - poSurface.exist = pSrcMat->Get( pKey, static_cast(pType), static_cast(pIndex), poSurface.color) == aiReturn_SUCCESS; - } -} - -static bool isalnum_C(char c) { - return ( nullptr != strchr("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",c) ); -} - -// ------------------------------------------------------------------------------------------------ -// Writes an image entry for the given surface -void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::string& pNameAdd) { - if( !pSurface.texture.empty() ) - { - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << ""; - - // URL encode image file name first, then XML encode on top - std::stringstream imageUrlEncoded; - for( std::string::const_iterator it = pSurface.texture.begin(); it != pSurface.texture.end(); ++it ) - { - if( isalnum_C( (unsigned char) *it) || *it == ':' || *it == '_' || *it == '-' || *it == '.' || *it == '/' || *it == '\\' ) - imageUrlEncoded << *it; - else - imageUrlEncoded << '%' << std::hex << size_t( (unsigned char) *it) << std::dec; - } - mOutput << XMLEscape(imageUrlEncoded.str()); - mOutput << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - } -} - -// ------------------------------------------------------------------------------------------------ -// Writes a color-or-texture entry into an effect definition -void ColladaExporter::WriteTextureColorEntry( const Surface& pSurface, const std::string& pTypeName, const std::string& pImageName) -{ - if(pSurface.exist) { - mOutput << startstr << "<" << pTypeName << ">" << endstr; - PushTag(); - if( pSurface.texture.empty() ) - { - mOutput << startstr << "" << pSurface.color.r << " " << pSurface.color.g << " " << pSurface.color.b << " " << pSurface.color.a << "" << endstr; - } - else - { - mOutput << startstr << "" << endstr; - } - PopTag(); - mOutput << startstr << "" << endstr; - } -} - -// ------------------------------------------------------------------------------------------------ -// Writes the two parameters necessary for referencing a texture in an effect entry -void ColladaExporter::WriteTextureParamEntry( const Surface& pSurface, const std::string& pTypeName, const std::string& pMatName) -{ - // if surface is a texture, write out the sampler and the surface parameters necessary to reference the texture - if( !pSurface.texture.empty() ) - { - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << XMLIDEncode(pMatName) << "-" << pTypeName << "-image" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << XMLIDEncode(pMatName) << "-" << pTypeName << "-surface" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - } -} - -// ------------------------------------------------------------------------------------------------ -// Writes a scalar property -void ColladaExporter::WriteFloatEntry( const Property& pProperty, const std::string& pTypeName) -{ - if(pProperty.exist) { - mOutput << startstr << "<" << pTypeName << ">" << endstr; - PushTag(); - mOutput << startstr << "" << pProperty.value << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - } -} - -// ------------------------------------------------------------------------------------------------ -// Writes the material setup -void ColladaExporter::WriteMaterials() -{ - materials.resize( mScene->mNumMaterials); - - /// collect all materials from the scene - size_t numTextures = 0; - for( size_t a = 0; a < mScene->mNumMaterials; ++a ) - { - const aiMaterial* mat = mScene->mMaterials[a]; - - aiString name; - if( mat->Get( AI_MATKEY_NAME, name) != aiReturn_SUCCESS ) { - name = "mat"; - materials[a].name = std::string( "m") + to_string(a) + name.C_Str(); - } else { - // try to use the material's name if no other material has already taken it, else append # - std::string testName = name.C_Str(); - size_t materialCountWithThisName = 0; - for( size_t i = 0; i < a; i ++ ) { - if( materials[i].name == testName ) { - materialCountWithThisName ++; - } - } - if( materialCountWithThisName == 0 ) { - materials[a].name = name.C_Str(); - } else { - materials[a].name = std::string(name.C_Str()) + to_string(materialCountWithThisName); - } - } - - aiShadingMode shading = aiShadingMode_Flat; - materials[a].shading_model = "phong"; - if(mat->Get( AI_MATKEY_SHADING_MODEL, shading) == aiReturn_SUCCESS) { - if(shading == aiShadingMode_Phong) { - materials[a].shading_model = "phong"; - } else if(shading == aiShadingMode_Blinn) { - materials[a].shading_model = "blinn"; - } else if(shading == aiShadingMode_NoShading) { - materials[a].shading_model = "constant"; - } else if(shading == aiShadingMode_Gouraud) { - materials[a].shading_model = "lambert"; - } - } - - ReadMaterialSurface( materials[a].ambient, mat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT); - if( !materials[a].ambient.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].diffuse, mat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE); - if( !materials[a].diffuse.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].specular, mat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR); - if( !materials[a].specular.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].emissive, mat, aiTextureType_EMISSIVE, AI_MATKEY_COLOR_EMISSIVE); - if( !materials[a].emissive.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].reflective, mat, aiTextureType_REFLECTION, AI_MATKEY_COLOR_REFLECTIVE); - if( !materials[a].reflective.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].transparent, mat, aiTextureType_OPACITY, AI_MATKEY_COLOR_TRANSPARENT); - if( !materials[a].transparent.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].normal, mat, aiTextureType_NORMALS, NULL, 0, 0); - if( !materials[a].normal.texture.empty() ) numTextures++; - - materials[a].shininess.exist = mat->Get( AI_MATKEY_SHININESS, materials[a].shininess.value) == aiReturn_SUCCESS; - materials[a].transparency.exist = mat->Get( AI_MATKEY_OPACITY, materials[a].transparency.value) == aiReturn_SUCCESS; - materials[a].index_refraction.exist = mat->Get( AI_MATKEY_REFRACTI, materials[a].index_refraction.value) == aiReturn_SUCCESS; - } - - // output textures if present - if( numTextures > 0 ) - { - mOutput << startstr << "" << endstr; - PushTag(); - for( std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it ) - { - const Material& mat = *it; - WriteImageEntry( mat.ambient, mat.name + "-ambient-image"); - WriteImageEntry( mat.diffuse, mat.name + "-diffuse-image"); - WriteImageEntry( mat.specular, mat.name + "-specular-image"); - WriteImageEntry( mat.emissive, mat.name + "-emission-image"); - WriteImageEntry( mat.reflective, mat.name + "-reflective-image"); - WriteImageEntry( mat.transparent, mat.name + "-transparent-image"); - WriteImageEntry( mat.normal, mat.name + "-normal-image"); - } - PopTag(); - mOutput << startstr << "" << endstr; - } - - // output effects - those are the actual carriers of information - if( !materials.empty() ) - { - mOutput << startstr << "" << endstr; - PushTag(); - for( std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it ) - { - const Material& mat = *it; - // this is so ridiculous it must be right - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - - // write sampler- and surface params for the texture entries - WriteTextureParamEntry( mat.emissive, "emission", mat.name); - WriteTextureParamEntry( mat.ambient, "ambient", mat.name); - WriteTextureParamEntry( mat.diffuse, "diffuse", mat.name); - WriteTextureParamEntry( mat.specular, "specular", mat.name); - WriteTextureParamEntry( mat.reflective, "reflective", mat.name); - WriteTextureParamEntry( mat.transparent, "transparent", mat.name); - WriteTextureParamEntry( mat.normal, "normal", mat.name); - - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "<" << mat.shading_model << ">" << endstr; - PushTag(); - - WriteTextureColorEntry( mat.emissive, "emission", mat.name + "-emission-sampler"); - WriteTextureColorEntry( mat.ambient, "ambient", mat.name + "-ambient-sampler"); - WriteTextureColorEntry( mat.diffuse, "diffuse", mat.name + "-diffuse-sampler"); - WriteTextureColorEntry( mat.specular, "specular", mat.name + "-specular-sampler"); - WriteFloatEntry(mat.shininess, "shininess"); - WriteTextureColorEntry( mat.reflective, "reflective", mat.name + "-reflective-sampler"); - WriteTextureColorEntry( mat.transparent, "transparent", mat.name + "-transparent-sampler"); - WriteFloatEntry(mat.transparency, "transparency"); - WriteFloatEntry(mat.index_refraction, "index_of_refraction"); - - if(! mat.normal.texture.empty()) { - WriteTextureColorEntry( mat.normal, "bump", mat.name + "-normal-sampler"); - } - - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - } - PopTag(); - mOutput << startstr << "" << endstr; - - // write materials - they're just effect references - mOutput << startstr << "" << endstr; - PushTag(); - for( std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it ) - { - const Material& mat = *it; - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - } - PopTag(); - mOutput << startstr << "" << endstr; - } -} - -// ------------------------------------------------------------------------------------------------ -// Writes the controller library -void ColladaExporter::WriteControllerLibrary() -{ - mOutput << startstr << "" << endstr; - PushTag(); - - for( size_t a = 0; a < mScene->mNumMeshes; ++a) { - WriteController( a); - } - - PopTag(); - mOutput << startstr << "" << endstr; -} - -// ------------------------------------------------------------------------------------------------ -// Writes a skin controller of the given mesh -void ColladaExporter::WriteController( size_t pIndex) -{ - const aiMesh* mesh = mScene->mMeshes[pIndex]; - const std::string idstr = mesh->mName.length == 0 ? GetMeshId(pIndex) : mesh->mName.C_Str(); - const std::string idstrEscaped = XMLIDEncode(idstr); - - if ( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) - return; - - if ( mesh->mNumBones == 0 ) - return; - - mOutput << startstr << ""<< endstr; - PushTag(); - - mOutput << startstr << "" << endstr; - PushTag(); - - // bind pose matrix - mOutput << startstr << "" << endstr; - PushTag(); - - // I think it is identity in general cases. - aiMatrix4x4 mat; - mOutput << startstr << mat.a1 << " " << mat.a2 << " " << mat.a3 << " " << mat.a4 << endstr; - mOutput << startstr << mat.b1 << " " << mat.b2 << " " << mat.b3 << " " << mat.b4 << endstr; - mOutput << startstr << mat.c1 << " " << mat.c2 << " " << mat.c3 << " " << mat.c4 << endstr; - mOutput << startstr << mat.d1 << " " << mat.d2 << " " << mat.d3 << " " << mat.d4 << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - - mOutput << startstr << "" << endstr; - PushTag(); - - mOutput << startstr << "mNumBones << "\">"; - - for( size_t i = 0; i < mesh->mNumBones; ++i ) - mOutput << XMLIDEncode(mesh->mBones[i]->mName.C_Str()) << " "; - - mOutput << "" << endstr; - - mOutput << startstr << "" << endstr; - PushTag(); - - mOutput << startstr << "mNumBones << "\" stride=\"" << 1 << "\">" << endstr; - PushTag(); - - mOutput << startstr << "" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - - std::vector bind_poses; - bind_poses.reserve(mesh->mNumBones * 16); - for(unsigned int i = 0; i < mesh->mNumBones; ++i) - for( unsigned int j = 0; j < 4; ++j) - bind_poses.insert(bind_poses.end(), mesh->mBones[i]->mOffsetMatrix[j], mesh->mBones[i]->mOffsetMatrix[j] + 4); - - WriteFloatArray( idstr + "-skin-bind_poses", FloatType_Mat4x4, (const ai_real*) bind_poses.data(), bind_poses.size() / 16); - - bind_poses.clear(); - - std::vector skin_weights; - skin_weights.reserve(mesh->mNumVertices * mesh->mNumBones); - for( size_t i = 0; i < mesh->mNumBones; ++i) - for( size_t j = 0; j < mesh->mBones[i]->mNumWeights; ++j) - skin_weights.push_back(mesh->mBones[i]->mWeights[j].mWeight); - - WriteFloatArray( idstr + "-skin-weights", FloatType_Weight, (const ai_real*) skin_weights.data(), skin_weights.size()); - - skin_weights.clear(); - - mOutput << startstr << "" << endstr; - PushTag(); - - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - - mOutput << startstr << "mNumVertices << "\">" << endstr; - PushTag(); - - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - - mOutput << startstr << ""; - - std::vector num_influences(mesh->mNumVertices, (ai_uint)0); - for( size_t i = 0; i < mesh->mNumBones; ++i) - for( size_t j = 0; j < mesh->mBones[i]->mNumWeights; ++j) - ++num_influences[mesh->mBones[i]->mWeights[j].mVertexId]; - - for( size_t i = 0; i < mesh->mNumVertices; ++i) - mOutput << num_influences[i] << " "; - - mOutput << "" << endstr; - - mOutput << startstr << ""; - - ai_uint joint_weight_indices_length = 0; - std::vector accum_influences; - accum_influences.reserve(num_influences.size()); - for( size_t i = 0; i < num_influences.size(); ++i) - { - accum_influences.push_back(joint_weight_indices_length); - joint_weight_indices_length += num_influences[i]; - } - - ai_uint weight_index = 0; - std::vector joint_weight_indices(2 * joint_weight_indices_length, (ai_int)-1); - for( unsigned int i = 0; i < mesh->mNumBones; ++i) - for( unsigned j = 0; j < mesh->mBones[i]->mNumWeights; ++j) - { - unsigned int vId = mesh->mBones[i]->mWeights[j].mVertexId; - for( ai_uint k = 0; k < num_influences[vId]; ++k) - { - if (joint_weight_indices[2 * (accum_influences[vId] + k)] == -1) - { - joint_weight_indices[2 * (accum_influences[vId] + k)] = i; - joint_weight_indices[2 * (accum_influences[vId] + k) + 1] = weight_index; - break; - } - } - ++weight_index; - } - - for( size_t i = 0; i < joint_weight_indices.size(); ++i) - mOutput << joint_weight_indices[i] << " "; - - num_influences.clear(); - accum_influences.clear(); - joint_weight_indices.clear(); - - mOutput << "" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; -} - -// ------------------------------------------------------------------------------------------------ -// Writes the geometry library -void ColladaExporter::WriteGeometryLibrary() -{ - mOutput << startstr << "" << endstr; - PushTag(); - - for( size_t a = 0; a < mScene->mNumMeshes; ++a) - WriteGeometry( a); - - PopTag(); - mOutput << startstr << "" << endstr; -} - -// ------------------------------------------------------------------------------------------------ -// Writes the given mesh -void ColladaExporter::WriteGeometry( size_t pIndex) -{ - const aiMesh* mesh = mScene->mMeshes[pIndex]; - const std::string idstr = mesh->mName.length == 0 ? GetMeshId(pIndex) : mesh->mName.C_Str(); - const std::string geometryName = XMLEscape(idstr); - const std::string geometryId = XMLIDEncode(idstr); - - if ( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) - return; - - // opening tag - mOutput << startstr << "" << endstr; - PushTag(); - - mOutput << startstr << "" << endstr; - PushTag(); - - // Positions - WriteFloatArray( idstr + "-positions", FloatType_Vector, (ai_real*) mesh->mVertices, mesh->mNumVertices); - // Normals, if any - if( mesh->HasNormals() ) - WriteFloatArray( idstr + "-normals", FloatType_Vector, (ai_real*) mesh->mNormals, mesh->mNumVertices); - - // texture coords - for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) - { - if( mesh->HasTextureCoords(static_cast(a)) ) - { - WriteFloatArray( idstr + "-tex" + to_string(a), mesh->mNumUVComponents[a] == 3 ? FloatType_TexCoord3 : FloatType_TexCoord2, - (ai_real*) mesh->mTextureCoords[a], mesh->mNumVertices); - } - } - - // vertex colors - for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) - { - if( mesh->HasVertexColors(static_cast(a)) ) - WriteFloatArray( idstr + "-color" + to_string(a), FloatType_Color, (ai_real*) mesh->mColors[a], mesh->mNumVertices); - } - - // assemble vertex structure - // Only write input for POSITION since we will write other as shared inputs in polygon definition - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - - // count the number of lines, triangles and polygon meshes - int countLines = 0; - int countPoly = 0; - for( size_t a = 0; a < mesh->mNumFaces; ++a ) - { - if (mesh->mFaces[a].mNumIndices == 2) countLines++; - else if (mesh->mFaces[a].mNumIndices >= 3) countPoly++; - } - - // lines - if (countLines) - { - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - if( mesh->HasNormals() ) - mOutput << startstr << "" << endstr; - for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) - { - if( mesh->HasTextureCoords(static_cast(a)) ) - mOutput << startstr << "" << endstr; - } - for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a ) - { - if( mesh->HasVertexColors(static_cast(a) ) ) - mOutput << startstr << "" << endstr; - } - - mOutput << startstr << "

"; - for( size_t a = 0; a < mesh->mNumFaces; ++a ) - { - const aiFace& face = mesh->mFaces[a]; - if (face.mNumIndices != 2) continue; - for( size_t b = 0; b < face.mNumIndices; ++b ) - mOutput << face.mIndices[b] << " "; - } - mOutput << "

" << endstr; - PopTag(); - mOutput << startstr << "
" << endstr; - } - - // triangle - don't use it, because compatibility problems - - // polygons - if (countPoly) - { - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - if( mesh->HasNormals() ) - mOutput << startstr << "" << endstr; - for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) - { - if( mesh->HasTextureCoords(static_cast(a)) ) - mOutput << startstr << "" << endstr; - } - for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a ) - { - if( mesh->HasVertexColors(static_cast(a) ) ) - mOutput << startstr << "" << endstr; - } - - mOutput << startstr << ""; - for( size_t a = 0; a < mesh->mNumFaces; ++a ) - { - if (mesh->mFaces[a].mNumIndices < 3) continue; - mOutput << mesh->mFaces[a].mNumIndices << " "; - } - mOutput << "" << endstr; - - mOutput << startstr << "

"; - for( size_t a = 0; a < mesh->mNumFaces; ++a ) - { - const aiFace& face = mesh->mFaces[a]; - if (face.mNumIndices < 3) continue; - for( size_t b = 0; b < face.mNumIndices; ++b ) - mOutput << face.mIndices[b] << " "; - } - mOutput << "

" << endstr; - PopTag(); - mOutput << startstr << "
" << endstr; - } - - // closing tags - PopTag(); - mOutput << startstr << "
" << endstr; - PopTag(); - mOutput << startstr << "
" << endstr; -} - -// ------------------------------------------------------------------------------------------------ -// Writes a float array of the given type -void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataType pType, const ai_real* pData, size_t pElementCount) -{ - size_t floatsPerElement = 0; - switch( pType ) - { - case FloatType_Vector: floatsPerElement = 3; break; - case FloatType_TexCoord2: floatsPerElement = 2; break; - case FloatType_TexCoord3: floatsPerElement = 3; break; - case FloatType_Color: floatsPerElement = 3; break; - case FloatType_Mat4x4: floatsPerElement = 16; break; - case FloatType_Weight: floatsPerElement = 1; break; - case FloatType_Time: floatsPerElement = 1; break; - default: - return; - } - - std::string arrayId = XMLIDEncode(pIdString) + "-array"; - - mOutput << startstr << "" << endstr; - PushTag(); - - // source array - mOutput << startstr << " "; - PushTag(); - - if( pType == FloatType_TexCoord2 ) - { - for( size_t a = 0; a < pElementCount; ++a ) - { - mOutput << pData[a*3+0] << " "; - mOutput << pData[a*3+1] << " "; - } - } - else if( pType == FloatType_Color ) - { - for( size_t a = 0; a < pElementCount; ++a ) - { - mOutput << pData[a*4+0] << " "; - mOutput << pData[a*4+1] << " "; - mOutput << pData[a*4+2] << " "; - } - } - else - { - for( size_t a = 0; a < pElementCount * floatsPerElement; ++a ) - mOutput << pData[a] << " "; - } - mOutput << "" << endstr; - PopTag(); - - // the usual Collada fun. Let's bloat it even more! - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - - switch( pType ) - { - case FloatType_Vector: - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - break; - - case FloatType_TexCoord2: - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - break; - - case FloatType_TexCoord3: - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - break; - - case FloatType_Color: - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; - break; - - case FloatType_Mat4x4: - mOutput << startstr << "" << endstr; - break; - - case FloatType_Weight: - mOutput << startstr << "" << endstr; - break; - - // customized, add animation related - case FloatType_Time: - mOutput << startstr << "" << endstr; - break; - - } - - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; -} - -// ------------------------------------------------------------------------------------------------ -// Writes the scene library -void ColladaExporter::WriteSceneLibrary() -{ - const std::string sceneName = XMLEscape(mScene->mRootNode->mName.C_Str()); - const std::string sceneId = XMLIDEncode(mScene->mRootNode->mName.C_Str()); - - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - - // start recursive write at the root node - for( size_t a = 0; a < mScene->mRootNode->mNumChildren; ++a ) - WriteNode( mScene, mScene->mRootNode->mChildren[a]); - - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; -} -// ------------------------------------------------------------------------------------------------ -void ColladaExporter::WriteAnimationLibrary(size_t pIndex) -{ - static const float kSecondsFromMilliseconds = .001f; - - const aiAnimation * anim = mScene->mAnimations[pIndex]; - - if ( anim->mNumChannels == 0 && anim->mNumMeshChannels == 0 && anim->mNumMorphMeshChannels ==0 ) { - return; - } - - const std::string animation_name_escaped = XMLEscape( anim->mName.C_Str() ); - std::string idstr = anim->mName.C_Str(); - std::string ending = std::string( "AnimId" ) + to_string(pIndex); - if (idstr.length() >= ending.length()) { - if (0 != idstr.compare (idstr.length() - ending.length(), ending.length(), ending)) { - idstr = idstr + ending; - } - } else { - idstr = idstr + ending; - } - - const std::string idstrEscaped = XMLIDEncode(idstr); - - mOutput << startstr << "" << endstr; - PushTag(); - - std::string cur_node_idstr; - for (size_t a = 0; a < anim->mNumChannels; ++a) { - const aiNodeAnim * nodeAnim = anim->mChannels[a]; - - // sanity check - if (nodeAnim->mNumPositionKeys != nodeAnim->mNumScalingKeys || nodeAnim->mNumPositionKeys != nodeAnim->mNumRotationKeys) { - continue; - } - - { - cur_node_idstr.clear(); - cur_node_idstr += nodeAnim->mNodeName.data; - cur_node_idstr += std::string("_matrix-input"); - - std::vector frames; - for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) { - frames.push_back(static_cast(nodeAnim->mPositionKeys[i].mTime) * kSecondsFromMilliseconds); - } - - WriteFloatArray(cur_node_idstr, FloatType_Time, (const ai_real *)frames.data(), frames.size()); - frames.clear(); - } - - { - cur_node_idstr.clear(); - - cur_node_idstr += nodeAnim->mNodeName.data; - cur_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; - - aiQuaternion RotationQ = nodeAnim->mRotationKeys[i].mValue; - aiMatrix4x4 s = aiMatrix4x4( RotationQ.GetMatrix() ); - aiMatrix4x4 RotationM(s.a1, s.a2, s.a3, 0, s.b1, s.b2, s.b3, 0, s.c1, s.c2, s.c3, 0, 0, 0, 0, 1); - - aiVector3D Translation = nodeAnim->mPositionKeys[i].mValue; - aiMatrix4x4 TranslationM; // identity - TranslationM[0][3] = Translation.x; TranslationM[1][3] = Translation.y; TranslationM[2][3] = Translation.z; - - // Combine the above transformations - aiMatrix4x4 mat = TranslationM * RotationM * ScalingM; - - for( unsigned int j = 0; j < 4; ++j) { - keyframes.insert(keyframes.end(), mat[j], mat[j] + 4); - } - } - - WriteFloatArray(cur_node_idstr, FloatType_Mat4x4, (const ai_real *)keyframes.data(), keyframes.size() / 16); - } - - { - std::vector names; - for ( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) { - if ( nodeAnim->mPreState == aiAnimBehaviour_DEFAULT - || nodeAnim->mPreState == aiAnimBehaviour_LINEAR - || nodeAnim->mPreState == aiAnimBehaviour_REPEAT - ) { - names.push_back( "LINEAR" ); - } else if (nodeAnim->mPostState == aiAnimBehaviour_CONSTANT) { - names.push_back( "STEP" ); - } - } - - const std::string cur_node_idstr2 = nodeAnim->mNodeName.data + std::string("_matrix-interpolation"); - std::string arrayId = XMLIDEncode(cur_node_idstr2) + "-array"; - - mOutput << startstr << "" << endstr; - PushTag(); - - // source array - mOutput << startstr << " "; - for( size_t aa = 0; aa < names.size(); ++aa ) { - mOutput << names[aa] << " "; - } - mOutput << "" << endstr; - - mOutput << startstr << "" << endstr; - PushTag(); - - mOutput << startstr << "" << endstr; - PushTag(); - - mOutput << startstr << "" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - } - } - - for (size_t a = 0; a < anim->mNumChannels; ++a) { - const aiNodeAnim * nodeAnim = anim->mChannels[a]; - - { - // samplers - const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-sampler"); - mOutput << startstr << "" << endstr; - PushTag(); - - mOutput << startstr << "mNodeName.data + std::string("_matrix-input") ) << "\"/>" << endstr; - mOutput << startstr << "mNodeName.data + std::string("_matrix-output") ) << "\"/>" << endstr; - mOutput << startstr << "mNodeName.data + std::string("_matrix-interpolation") ) << "\"/>" << endstr; - - PopTag(); - mOutput << startstr << "" << endstr; - } - } - - for (size_t a = 0; a < anim->mNumChannels; ++a) { - const aiNodeAnim * nodeAnim = anim->mChannels[a]; - - { - // channels - mOutput << startstr << "mNodeName.data + std::string("_matrix-sampler") ) << "\" target=\"" << XMLIDEncode(nodeAnim->mNodeName.data) << "/matrix\"/>" << endstr; - } - } - - PopTag(); - mOutput << startstr << "" << endstr; - -} -// ------------------------------------------------------------------------------------------------ -void ColladaExporter::WriteAnimationsLibrary() -{ - if ( mScene->mNumAnimations > 0 ) { - mOutput << startstr << "" << endstr; - PushTag(); - - // start recursive write at the root node - for( size_t a = 0; a < mScene->mNumAnimations; ++a) - WriteAnimationLibrary( a ); - - PopTag(); - mOutput << startstr << "" << endstr; - } -} -// ------------------------------------------------------------------------------------------------ -// Helper to find a bone by name in the scene -aiBone* findBone( const aiScene* scene, const char * name) { - for (size_t m=0; mmNumMeshes; m++) { - aiMesh * mesh = scene->mMeshes[m]; - for (size_t b=0; bmNumBones; b++) { - aiBone * bone = mesh->mBones[b]; - if (0 == strcmp(name, bone->mName.C_Str())) { - return bone; - } - } - } - return NULL; -} - -// ------------------------------------------------------------------------------------------------ -const aiNode * findBoneNode( const aiNode* aNode, const aiBone* bone) -{ - if ( aNode && bone && aNode->mName == bone->mName ) { - return aNode; - } - - if ( aNode && bone ) { - for (unsigned int i=0; i < aNode->mNumChildren; ++i) { - aiNode * aChild = aNode->mChildren[i]; - const aiNode * foundFromChild = 0; - if ( aChild ) { - foundFromChild = findBoneNode( aChild, bone ); - if ( foundFromChild ) return foundFromChild; - } - } - } - - return NULL; -} - -const aiNode * findSkeletonRootNode( const aiScene* scene, const aiMesh * mesh) -{ - std::set topParentBoneNodes; - if ( mesh && mesh->mNumBones > 0 ) { - for (unsigned int i=0; i < mesh->mNumBones; ++i) { - aiBone * bone = mesh->mBones[i]; - - const aiNode * node = findBoneNode( scene->mRootNode, bone); - if ( node ) { - while ( node->mParent && findBone(scene, node->mParent->mName.C_Str() ) != 0 ) { - node = node->mParent; - } - topParentBoneNodes.insert( node ); - } - } - } - - if ( !topParentBoneNodes.empty() ) { - const aiNode * parentBoneNode = *topParentBoneNodes.begin(); - if ( topParentBoneNodes.size() == 1 ) { - return parentBoneNode; - } else { - for (auto it : topParentBoneNodes) { - if ( it->mParent ) return it->mParent; - } - return parentBoneNode; - } - } - - return NULL; -} - -// ------------------------------------------------------------------------------------------------ -// Recursively writes the given node -void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) -{ - // the node must have a name - if (pNode->mName.length == 0) - { - std::stringstream ss; - ss << "Node_" << pNode; - pNode->mName.Set(ss.str()); - } - - // If the node is associated with a bone, it is a joint node (JOINT) - // otherwise it is a normal node (NODE) - const char * node_type; - bool is_joint, is_skeleton_root = false; - if (nullptr == findBone(pScene, pNode->mName.C_Str())) { - node_type = "NODE"; - is_joint = false; - } else { - node_type = "JOINT"; - is_joint = true; - if (!pNode->mParent || nullptr == findBone(pScene, pNode->mParent->mName.C_Str())) { - is_skeleton_root = true; - } - } - - const std::string node_id = XMLIDEncode(pNode->mName.data); - const std::string node_name = XMLEscape(pNode->mName.data); - mOutput << startstr << "" << endstr; - PushTag(); - - // write transformation - we can directly put the matrix there - // TODO: (thom) decompose into scale - rot - quad to allow addressing it by animations afterwards - aiMatrix4x4 mat = pNode->mTransformation; - - // If this node is a Camera node, the camera coordinate system needs to be multiplied in. - // When importing from Collada, the mLookAt is set to 0, 0, -1, and the node transform is unchanged. - // When importing from a different format, mLookAt is set to 0, 0, 1. Therefore, the local camera - // coordinate system must be changed to matche the Collada specification. - for (size_t i = 0; imNumCameras; i++){ - if (mScene->mCameras[i]->mName == pNode->mName){ - aiMatrix4x4 sourceView; - mScene->mCameras[i]->GetCameraMatrix(sourceView); - - aiMatrix4x4 colladaView; - colladaView.a1 = colladaView.c3 = -1; // move into -z space. - mat *= (sourceView * colladaView); - break; - } - } - - // customized, sid should be 'matrix' to match with loader code. - //mOutput << startstr << ""; - mOutput << startstr << ""; - - mOutput << mat.a1 << " " << mat.a2 << " " << mat.a3 << " " << mat.a4 << " "; - mOutput << mat.b1 << " " << mat.b2 << " " << mat.b3 << " " << mat.b4 << " "; - mOutput << mat.c1 << " " << mat.c2 << " " << mat.c3 << " " << mat.c4 << " "; - mOutput << mat.d1 << " " << mat.d2 << " " << mat.d3 << " " << mat.d4; - mOutput << "" << endstr; - - if(pNode->mNumMeshes==0){ - //check if it is a camera node - for(size_t i=0; imNumCameras; i++){ - if(mScene->mCameras[i]->mName == pNode->mName){ - mOutput << startstr <<"" << endstr; - break; - } - } - //check if it is a light node - for(size_t i=0; imNumLights; i++){ - if(mScene->mLights[i]->mName == pNode->mName){ - mOutput << startstr <<"" << endstr; - break; - } - } - - }else - // instance every geometry - for( size_t a = 0; a < pNode->mNumMeshes; ++a ) - { - const aiMesh* mesh = mScene->mMeshes[pNode->mMeshes[a]]; - // do not instantiate mesh if empty. I wonder how this could happen - if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) - continue; - - const std::string meshName = mesh->mName.length == 0 ? GetMeshId(pNode->mMeshes[a]) : mesh->mName.C_Str(); - - if( mesh->mNumBones == 0 ) - { - mOutput << startstr << "" << endstr; - PushTag(); - } - else - { - mOutput << startstr - << "" - << endstr; - PushTag(); - - // note! this mFoundSkeletonRootNodeID some how affects animation, it makes the mesh attaches to armature skeleton root node. - // use the first bone to find skeleton root - const aiNode * skeletonRootBoneNode = findSkeletonRootNode( pScene, mesh ); - if ( skeletonRootBoneNode ) { - mFoundSkeletonRootNodeID = XMLIDEncode( skeletonRootBoneNode->mName.C_Str() ); - } - mOutput << startstr << "#" << mFoundSkeletonRootNodeID << "" << endstr; - } - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "mMaterialIndex].name) << "\">" << endstr; - PushTag(); - for( size_t aa = 0; aa < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++aa ) - { - if( mesh->HasTextureCoords( static_cast(aa) ) ) - // semantic as in - // input_semantic as in - // input_set as in - mOutput << startstr << "" << endstr; - } - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - - PopTag(); - if( mesh->mNumBones == 0) - mOutput << startstr << "" << endstr; - else - mOutput << startstr << "" << endstr; - } - - // recurse into subnodes - for( size_t a = 0; a < pNode->mNumChildren; ++a ) - WriteNode( pScene, pNode->mChildren[a]); - - PopTag(); - mOutput << startstr << "" << endstr; -} - -#endif -#endif From c82f8c0b8f39b26304a590f24e91b097849c5d1c Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 25 May 2020 20:38:12 +0200 Subject: [PATCH 20/21] Remove duplicated code closes https://github.com/assimp/assimp/issues/3183 --- tools/assimp_view/Display.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/assimp_view/Display.cpp b/tools/assimp_view/Display.cpp index 9fa157c41..1f6bb89eb 100644 --- a/tools/assimp_view/Display.cpp +++ b/tools/assimp_view/Display.cpp @@ -462,7 +462,7 @@ int CDisplay::AddTextureToDisplayList(unsigned int iType, TVINSERTSTRUCT sNew; tvi.pszText = chTemp; tvi.cchTextMax = (int)strlen(chTemp); - tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE | TVIF_HANDLE; + tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE; tvi.lParam = (LPARAM)20; // find out whether this is the default texture or not From c94ed5c7b1edda974bd0613f26af675e6f53b3ec Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 25 May 2020 20:40:19 +0200 Subject: [PATCH 21/21] Update utRemoveComponent.cpp closes https://github.com/assimp/assimp/issues/3183 --- test/unit/utRemoveComponent.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/test/unit/utRemoveComponent.cpp b/test/unit/utRemoveComponent.cpp index d3c102cfb..622a582d6 100644 --- a/test/unit/utRemoveComponent.cpp +++ b/test/unit/utRemoveComponent.cpp @@ -98,13 +98,6 @@ void RemoveVCProcessTest::SetUp() { pScene->mCameras = new aiCamera *[pScene->mNumCameras = 2]; pScene->mCameras[0] = new aiCamera(); pScene->mCameras[1] = new aiCamera(); - - // COMPILE TEST: aiMaterial may no add any extra members, - // so we don't need a virtual destructor - char check[sizeof(aiMaterial) == sizeof(aiMaterial) ? 10 : -1]; - check[0] = 0; - // to remove compiler warning - EXPECT_EQ(0, check[0]); } // ------------------------------------------------------------------------------------------------