From 3d0775eebc0f2a86b87752385782e9b90c83279f Mon Sep 17 00:00:00 2001 From: ywang Date: Mon, 12 Aug 2019 18:10:43 -0700 Subject: [PATCH 01/12] respect export flag if aiJoinIdenticalVertices is not needed --- code/Common/Exporter.cpp | 5 ++- code/FBX/FBXExporter.cpp | 68 +++++++++++++++++++--------------------- 2 files changed, 37 insertions(+), 36 deletions(-) diff --git a/code/Common/Exporter.cpp b/code/Common/Exporter.cpp index 090b561ae..88bd9916f 100644 --- a/code/Common/Exporter.cpp +++ b/code/Common/Exporter.cpp @@ -472,7 +472,10 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c } ExportProperties emptyProperties; // Never pass NULL ExportProperties so Exporters don't have to worry. - exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProperties ? pProperties : &emptyProperties); + ExportProperties* pProp = pProperties ? (ExportProperties*)pProperties : &emptyProperties; + pProp->SetPropertyBool("bJoinIdenticalVertices", must_join_again); + exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProp); + exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProp); pimpl->mProgressHandler->UpdateFileWrite(4, 4); } catch (DeadlyExportError& err) { diff --git a/code/FBX/FBXExporter.cpp b/code/FBX/FBXExporter.cpp index 8ebc8555a..0722a0fba 100644 --- a/code/FBX/FBXExporter.cpp +++ b/code/FBX/FBXExporter.cpp @@ -67,6 +67,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include // RESOURCES: // https://code.blender.org/2013/08/fbx-binary-file-format-specification/ @@ -1005,6 +1006,9 @@ void FBXExporter::WriteObjects () object_node.EndProperties(outstream, binary, indent); object_node.BeginChildren(outstream, binary, indent); + bool bJoinIdenticalVertices = mProperties->GetPropertyBool("bJoinIdenticalVertices", true); + std::vector> vVertexIndice;//save vertex_indices as it is needed later + // geometry (aiMesh) mesh_uids.clear(); indent = 1; @@ -1031,21 +1035,35 @@ void FBXExporter::WriteObjects () std::vector vertex_indices; // map of vertex value to its index in the data vector std::map index_by_vertex_value; - int32_t index = 0; - for (size_t vi = 0; vi < m->mNumVertices; ++vi) { - aiVector3D vtx = m->mVertices[vi]; - auto elem = index_by_vertex_value.find(vtx); - if (elem == index_by_vertex_value.end()) { - vertex_indices.push_back(index); - index_by_vertex_value[vtx] = index; - flattened_vertices.push_back(vtx[0]); - flattened_vertices.push_back(vtx[1]); - flattened_vertices.push_back(vtx[2]); - ++index; - } else { - vertex_indices.push_back(int32_t(elem->second)); + if(bJoinIdenticalVertices){ + int32_t index = 0; + for (size_t vi = 0; vi < m->mNumVertices; ++vi) { + aiVector3D vtx = m->mVertices[vi]; + auto elem = index_by_vertex_value.find(vtx); + if (elem == index_by_vertex_value.end()) { + vertex_indices.push_back(index); + index_by_vertex_value[vtx] = index; + flattened_vertices.push_back(vtx[0]); + flattened_vertices.push_back(vtx[1]); + flattened_vertices.push_back(vtx[2]); + ++index; + } else { + vertex_indices.push_back(int32_t(elem->second)); + } } } + else { // do not join vertex, respect the export flag + vertex_indices.resize(m->mNumVertices); + std::iota(vertex_indices.begin(), vertex_indices.end(), 0); + for(unsigned int v = 0; v < m->mNumVertices; ++ v) { + aiVector3D vtx = m->mVertices[v]; + flattened_vertices.push_back(vtx.x); + flattened_vertices.push_back(vtx.y); + flattened_vertices.push_back(vtx.z); + } + } + vVertexIndice.push_back(vertex_indices); + FBX::Node::WritePropertyNode( "Vertices", flattened_vertices, outstream, binary, indent ); @@ -1748,28 +1766,8 @@ void FBXExporter::WriteObjects () // connect it connections.emplace_back("C", "OO", deformer_uid, mesh_uids[mi]); - // we will be indexing by vertex... - // but there might be a different number of "vertices" - // between assimp and our output FBX. - // this code is cut-and-pasted from the geometry section above... - // ideally this should not be so. - // --- - // index of original vertex in vertex data vector - std::vector vertex_indices; - // map of vertex value to its index in the data vector - std::map index_by_vertex_value; - int32_t index = 0; - for (size_t vi = 0; vi < m->mNumVertices; ++vi) { - aiVector3D vtx = m->mVertices[vi]; - auto elem = index_by_vertex_value.find(vtx); - if (elem == index_by_vertex_value.end()) { - vertex_indices.push_back(index); - index_by_vertex_value[vtx] = index; - ++index; - } else { - vertex_indices.push_back(int32_t(elem->second)); - } - } + //computed before + std::vector& vertex_indices = vVertexIndice[mi]; // TODO, FIXME: this won't work if anything is not in the bind pose. // for now if such a situation is detected, we throw an exception. From 727cf0c49f552073fe022c4ec24526dc0c561df0 Mon Sep 17 00:00:00 2001 From: Ryan McCampbell Date: Mon, 8 Jul 2019 23:21:57 -0700 Subject: [PATCH 02/12] Fixed unicode on windows --- code/Common/DefaultIOSystem.cpp | 80 +++++++++------------------------ 1 file changed, 20 insertions(+), 60 deletions(-) diff --git a/code/Common/DefaultIOSystem.cpp b/code/Common/DefaultIOSystem.cpp index d40b67de3..7606d8ced 100644 --- a/code/Common/DefaultIOSystem.cpp +++ b/code/Common/DefaultIOSystem.cpp @@ -73,28 +73,14 @@ using namespace Assimp; // Tests for the existence of a file at the given path. bool DefaultIOSystem::Exists( const char* pFile) const { -#ifdef _WIN32 +#if defined(_WIN32) && !defined(WindowsStore) wchar_t fileName16[PATHLIMIT]; -#ifndef WindowsStore - bool isUnicode = IsTextUnicode(pFile, static_cast(strlen(pFile)), NULL) != 0; - if (isUnicode) { - - MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, pFile, -1, fileName16, PATHLIMIT); - struct __stat64 filestat; - if (0 != _wstat64(fileName16, &filestat)) { - return false; - } - } else { -#endif - FILE* file = ::fopen(pFile, "rb"); - if (!file) - return false; - - ::fclose(file); -#ifndef WindowsStore + MultiByteToWideChar(CP_UTF8, 0, pFile, -1, fileName16, PATHLIMIT); + struct __stat64 filestat; + if (0 != _wstat64(fileName16, &filestat)) { + return false; } -#endif #else FILE* file = ::fopen( pFile, "rb"); if( !file) @@ -112,27 +98,19 @@ IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode) ai_assert(NULL != strFile); ai_assert(NULL != strMode); FILE* file; -#ifdef _WIN32 +#if defined(_WIN32) && !defined(WindowsStore) wchar_t fileName16[PATHLIMIT]; -#ifndef WindowsStore - bool isUnicode = IsTextUnicode(strFile, static_cast(strlen(strFile)), NULL) != 0; - if (isUnicode) { - MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, strFile, -1, fileName16, PATHLIMIT); - std::string mode8(strMode); - file = ::_wfopen(fileName16, std::wstring(mode8.begin(), mode8.end()).c_str()); - } else { -#endif - file = ::fopen(strFile, strMode); -#ifndef WindowsStore - } -#endif + MultiByteToWideChar(CP_UTF8, 0, strFile, -1, fileName16, PATHLIMIT); + std::string mode8(strMode); + std::wstring mode16(mode8.begin(), mode8.end()); + file = ::_wfopen(fileName16, mode16.c_str()); #else file = ::fopen(strFile, strMode); #endif if (nullptr == file) return nullptr; - return new DefaultIOStream(file, (std::string) strFile); + return new DefaultIOStream(file, strFile); } // ------------------------------------------------------------------------------------------------ @@ -167,44 +145,26 @@ inline static void MakeAbsolutePath (const char* in, char* _out) ai_assert(in && _out); #if defined( _MSC_VER ) || defined( __MINGW32__ ) #ifndef WindowsStore - bool isUnicode = IsTextUnicode(in, static_cast(strlen(in)), NULL) != 0; - if (isUnicode) { - wchar_t out16[PATHLIMIT]; - wchar_t in16[PATHLIMIT]; - MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, in, -1, out16, PATHLIMIT); - wchar_t* ret = ::_wfullpath(out16, in16, PATHLIMIT); - if (ret) { - WideCharToMultiByte(CP_UTF8, MB_PRECOMPOSED, out16, -1, _out, PATHLIMIT, nullptr, nullptr); - } - if (!ret) { - // preserve the input path, maybe someone else is able to fix - // the path before it is accessed (e.g. our file system filter) - ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in)); - strcpy(_out, in); - } - - } else { -#endif - char* ret = :: _fullpath(_out, in, PATHLIMIT); - if (!ret) { - // preserve the input path, maybe someone else is able to fix - // the path before it is accessed (e.g. our file system filter) - ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in)); - strcpy(_out, in); - } -#ifndef WindowsStore + wchar_t in16[PATHLIMIT]; + wchar_t out16[PATHLIMIT]; + MultiByteToWideChar(CP_UTF8, 0, in, -1, in16, PATHLIMIT); + wchar_t* ret = ::_wfullpath(out16, in16, PATHLIMIT); + if (ret) { + WideCharToMultiByte(CP_UTF8, 0, out16, -1, _out, PATHLIMIT, nullptr, nullptr); } +#else + char* ret = ::_fullpath(_out, in, PATHLIMIT); #endif #else // use realpath char* ret = realpath(in, _out); +#endif if(!ret) { // preserve the input path, maybe someone else is able to fix // the path before it is accessed (e.g. our file system filter) ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in)); strcpy(_out,in); } -#endif } // ------------------------------------------------------------------------------------------------ From 6c65b5b5496638c149907a605003f9a74f7bceb7 Mon Sep 17 00:00:00 2001 From: Ryan McCampbell Date: Tue, 9 Jul 2019 02:17:45 -0700 Subject: [PATCH 03/12] Cleaned up unicode code and removed fixed-size buffers --- code/Common/DefaultIOSystem.cpp | 74 ++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/code/Common/DefaultIOSystem.cpp b/code/Common/DefaultIOSystem.cpp index 7606d8ced..da7376809 100644 --- a/code/Common/DefaultIOSystem.cpp +++ b/code/Common/DefaultIOSystem.cpp @@ -61,12 +61,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; -// maximum path length -// XXX http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html -#ifdef PATH_MAX -# define PATHLIMIT PATH_MAX -#else -# define PATHLIMIT 4096 +#ifdef _WIN32 +static std::wstring Utf8ToWide(const char* in) +{ + int size = MultiByteToWideChar(CP_UTF8, 0, in, -1, nullptr, 0); + std::wstring out(size, L'\0'); + MultiByteToWideChar(CP_UTF8, 0, in, -1, &out[0], size); + return out; +} + +static std::string WideToUtf8(const wchar_t* in) +{ + int size = WideCharToMultiByte(CP_UTF8, 0, in, -1, nullptr, 0, nullptr, nullptr); + std::string out(size, '\0'); + WideCharToMultiByte(CP_UTF8, 0, in, -1, &out[0], size, nullptr, nullptr); + return out; +} #endif // ------------------------------------------------------------------------------------------------ @@ -74,11 +84,8 @@ using namespace Assimp; bool DefaultIOSystem::Exists( const char* pFile) const { #if defined(_WIN32) && !defined(WindowsStore) - wchar_t fileName16[PATHLIMIT]; - - MultiByteToWideChar(CP_UTF8, 0, pFile, -1, fileName16, PATHLIMIT); struct __stat64 filestat; - if (0 != _wstat64(fileName16, &filestat)) { + if (0 != _wstat64(Utf8ToWide(pFile).c_str(), &filestat)) { return false; } #else @@ -99,11 +106,7 @@ IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode) ai_assert(NULL != strMode); FILE* file; #if defined(_WIN32) && !defined(WindowsStore) - wchar_t fileName16[PATHLIMIT]; - MultiByteToWideChar(CP_UTF8, 0, strFile, -1, fileName16, PATHLIMIT); - std::string mode8(strMode); - std::wstring mode16(mode8.begin(), mode8.end()); - file = ::_wfopen(fileName16, mode16.c_str()); + file = ::_wfopen(Utf8ToWide(strFile).c_str(), Utf8ToWide(strMode).c_str()); #else file = ::fopen(strFile, strMode); #endif @@ -140,31 +143,39 @@ bool IOSystem::ComparePaths (const char* one, const char* second) const // ------------------------------------------------------------------------------------------------ // Convert a relative path into an absolute path -inline static void MakeAbsolutePath (const char* in, char* _out) +inline static std::string MakeAbsolutePath (const char* in) { - ai_assert(in && _out); -#if defined( _MSC_VER ) || defined( __MINGW32__ ) + ai_assert(in); + std::string out; +#ifdef _WIN32 #ifndef WindowsStore - wchar_t in16[PATHLIMIT]; - wchar_t out16[PATHLIMIT]; - MultiByteToWideChar(CP_UTF8, 0, in, -1, in16, PATHLIMIT); - wchar_t* ret = ::_wfullpath(out16, in16, PATHLIMIT); + wchar_t* ret = ::_wfullpath(nullptr, Utf8ToWide(in).c_str(), 0); if (ret) { - WideCharToMultiByte(CP_UTF8, 0, out16, -1, _out, PATHLIMIT, nullptr, nullptr); + out = WideToUtf8(ret); + free(ret); } #else - char* ret = ::_fullpath(_out, in, PATHLIMIT); + char* ret = ::_fullpath(nullptr, in, 0); + if (ret) { + out = ret; + free(ret); + } #endif #else // use realpath - char* ret = realpath(in, _out); + char* ret = realpath(in, nullptr); + if (ret) { + out = ret; + free(ret); + } #endif - if(!ret) { + if (!ret) { // preserve the input path, maybe someone else is able to fix // the path before it is accessed (e.g. our file system filter) ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in)); - strcpy(_out,in); + out = in; } + return out; } // ------------------------------------------------------------------------------------------------ @@ -176,11 +187,8 @@ bool DefaultIOSystem::ComparePaths (const char* one, const char* second) const if( !ASSIMP_stricmp(one,second) ) return true; - char temp1[PATHLIMIT]; - char temp2[PATHLIMIT]; - - MakeAbsolutePath (one, temp1); - MakeAbsolutePath (second, temp2); + std::string temp1 = MakeAbsolutePath(one); + std::string temp2 = MakeAbsolutePath(second); return !ASSIMP_stricmp(temp1,temp2); } @@ -213,5 +221,3 @@ std::string DefaultIOSystem::absolutePath( const std::string &path ) } // ------------------------------------------------------------------------------------------------ - -#undef PATHLIMIT From 0685e415ad6b32b23eef89315bd5658d9bf021c1 Mon Sep 17 00:00:00 2001 From: Ryan McCampbell Date: Mon, 19 Aug 2019 12:00:01 -0400 Subject: [PATCH 04/12] removed extra null character in Utf8ToWide and WideToUtf8 --- code/Common/DefaultIOSystem.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/code/Common/DefaultIOSystem.cpp b/code/Common/DefaultIOSystem.cpp index da7376809..7e26ec4b2 100644 --- a/code/Common/DefaultIOSystem.cpp +++ b/code/Common/DefaultIOSystem.cpp @@ -64,16 +64,18 @@ using namespace Assimp; #ifdef _WIN32 static std::wstring Utf8ToWide(const char* in) { - int size = MultiByteToWideChar(CP_UTF8, 0, in, -1, nullptr, 0); - std::wstring out(size, L'\0'); + size_t size = MultiByteToWideChar(CP_UTF8, 0, in, -1, nullptr, 0); + // size includes terminating null; std::wstring adds null automatically + std::wstring out(size - 1, L'\0'); MultiByteToWideChar(CP_UTF8, 0, in, -1, &out[0], size); return out; } static std::string WideToUtf8(const wchar_t* in) { - int size = WideCharToMultiByte(CP_UTF8, 0, in, -1, nullptr, 0, nullptr, nullptr); - std::string out(size, '\0'); + size_t size = WideCharToMultiByte(CP_UTF8, 0, in, -1, nullptr, 0, nullptr, nullptr); + // size includes terminating null; std::string adds null automatically + std::string out(size - 1, '\0'); WideCharToMultiByte(CP_UTF8, 0, in, -1, &out[0], size, nullptr, nullptr); return out; } From a8822a2b29514700202d586a5397481de93bcbd2 Mon Sep 17 00:00:00 2001 From: Ryan McCampbell Date: Mon, 19 Aug 2019 15:36:45 -0400 Subject: [PATCH 05/12] Cleaned up formatting in DefaultIOSystem.cpp --- code/Common/DefaultIOSystem.cpp | 40 ++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/code/Common/DefaultIOSystem.cpp b/code/Common/DefaultIOSystem.cpp index 7e26ec4b2..ce5996fa8 100644 --- a/code/Common/DefaultIOSystem.cpp +++ b/code/Common/DefaultIOSystem.cpp @@ -83,36 +83,36 @@ static std::string WideToUtf8(const wchar_t* in) // ------------------------------------------------------------------------------------------------ // Tests for the existence of a file at the given path. -bool DefaultIOSystem::Exists( const char* pFile) const +bool DefaultIOSystem::Exists(const char* pFile) const { #if defined(_WIN32) && !defined(WindowsStore) struct __stat64 filestat; - if (0 != _wstat64(Utf8ToWide(pFile).c_str(), &filestat)) { + if (_wstat64(Utf8ToWide(pFile).c_str(), &filestat) != 0) { return false; } #else - FILE* file = ::fopen( pFile, "rb"); - if( !file) + FILE* file = ::fopen(pFile, "rb"); + if (!file) return false; - ::fclose( file); + ::fclose(file); #endif return true; } // ------------------------------------------------------------------------------------------------ // Open a new file with a given path. -IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode) +IOStream* DefaultIOSystem::Open(const char* strFile, const char* strMode) { - ai_assert(NULL != strFile); - ai_assert(NULL != strMode); + ai_assert(strFile != nullptr); + ai_assert(strMode != nullptr); FILE* file; #if defined(_WIN32) && !defined(WindowsStore) file = ::_wfopen(Utf8ToWide(strFile).c_str(), Utf8ToWide(strMode).c_str()); #else file = ::fopen(strFile, strMode); #endif - if (nullptr == file) + if (!file) return nullptr; return new DefaultIOStream(file, strFile); @@ -120,7 +120,7 @@ IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode) // ------------------------------------------------------------------------------------------------ // Closes the given file and releases all resources associated with it. -void DefaultIOSystem::Close( IOStream* pFile) +void DefaultIOSystem::Close(IOStream* pFile) { delete pFile; } @@ -138,14 +138,14 @@ char DefaultIOSystem::getOsSeparator() const // ------------------------------------------------------------------------------------------------ // IOSystem default implementation (ComparePaths isn't a pure virtual function) -bool IOSystem::ComparePaths (const char* one, const char* second) const +bool IOSystem::ComparePaths(const char* one, const char* second) const { - return !ASSIMP_stricmp(one,second); + return !ASSIMP_stricmp(one, second); } // ------------------------------------------------------------------------------------------------ // Convert a relative path into an absolute path -inline static std::string MakeAbsolutePath (const char* in) +inline static std::string MakeAbsolutePath(const char* in) { ai_assert(in); std::string out; @@ -182,21 +182,21 @@ inline static std::string MakeAbsolutePath (const char* in) // ------------------------------------------------------------------------------------------------ // DefaultIOSystem's more specialized implementation -bool DefaultIOSystem::ComparePaths (const char* one, const char* second) const +bool DefaultIOSystem::ComparePaths(const char* one, const char* second) const { // chances are quite good both paths are formatted identically, // so we can hopefully return here already - if( !ASSIMP_stricmp(one,second) ) + if (!ASSIMP_stricmp(one, second)) return true; std::string temp1 = MakeAbsolutePath(one); std::string temp2 = MakeAbsolutePath(second); - return !ASSIMP_stricmp(temp1,temp2); + return !ASSIMP_stricmp(temp1, temp2); } // ------------------------------------------------------------------------------------------------ -std::string DefaultIOSystem::fileName( const std::string &path ) +std::string DefaultIOSystem::fileName(const std::string& path) { std::string ret = path; std::size_t last = ret.find_last_of("\\/"); @@ -205,16 +205,16 @@ std::string DefaultIOSystem::fileName( const std::string &path ) } // ------------------------------------------------------------------------------------------------ -std::string DefaultIOSystem::completeBaseName( const std::string &path ) +std::string DefaultIOSystem::completeBaseName(const std::string& path) { std::string ret = fileName(path); std::size_t pos = ret.find_last_of('.'); - if(pos != ret.npos) ret = ret.substr(0, pos); + if (pos != std::string::npos) ret = ret.substr(0, pos); return ret; } // ------------------------------------------------------------------------------------------------ -std::string DefaultIOSystem::absolutePath( const std::string &path ) +std::string DefaultIOSystem::absolutePath(const std::string& path) { std::string ret = path; std::size_t last = ret.find_last_of("\\/"); From a16906686f498cf4360c54ce41ef7838b1fecc84 Mon Sep 17 00:00:00 2001 From: Ryan McCampbell Date: Tue, 3 Sep 2019 21:06:48 -0400 Subject: [PATCH 06/12] Fixed type conversion warnings --- code/Common/DefaultIOSystem.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/Common/DefaultIOSystem.cpp b/code/Common/DefaultIOSystem.cpp index ce5996fa8..c0d356689 100644 --- a/code/Common/DefaultIOSystem.cpp +++ b/code/Common/DefaultIOSystem.cpp @@ -64,18 +64,18 @@ using namespace Assimp; #ifdef _WIN32 static std::wstring Utf8ToWide(const char* in) { - size_t size = MultiByteToWideChar(CP_UTF8, 0, in, -1, nullptr, 0); + int size = MultiByteToWideChar(CP_UTF8, 0, in, -1, nullptr, 0); // size includes terminating null; std::wstring adds null automatically - std::wstring out(size - 1, L'\0'); + std::wstring out(static_cast(size) - 1, L'\0'); MultiByteToWideChar(CP_UTF8, 0, in, -1, &out[0], size); return out; } static std::string WideToUtf8(const wchar_t* in) { - size_t size = WideCharToMultiByte(CP_UTF8, 0, in, -1, nullptr, 0, nullptr, nullptr); + int size = WideCharToMultiByte(CP_UTF8, 0, in, -1, nullptr, 0, nullptr, nullptr); // size includes terminating null; std::string adds null automatically - std::string out(size - 1, '\0'); + std::string out(static_cast(size) - 1, '\0'); WideCharToMultiByte(CP_UTF8, 0, in, -1, &out[0], size, nullptr, nullptr); return out; } From eb762e654eb73bf31220f1879d74254fb9332803 Mon Sep 17 00:00:00 2001 From: Ryan McCampbell Date: Tue, 3 Sep 2019 23:13:44 -0400 Subject: [PATCH 07/12] Removed WindowsStore checks --- code/Common/DefaultIOSystem.cpp | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/code/Common/DefaultIOSystem.cpp b/code/Common/DefaultIOSystem.cpp index c0d356689..6fdc24dd8 100644 --- a/code/Common/DefaultIOSystem.cpp +++ b/code/Common/DefaultIOSystem.cpp @@ -85,7 +85,7 @@ static std::string WideToUtf8(const wchar_t* in) // Tests for the existence of a file at the given path. bool DefaultIOSystem::Exists(const char* pFile) const { -#if defined(_WIN32) && !defined(WindowsStore) +#ifdef _WIN32 struct __stat64 filestat; if (_wstat64(Utf8ToWide(pFile).c_str(), &filestat) != 0) { return false; @@ -107,7 +107,7 @@ IOStream* DefaultIOSystem::Open(const char* strFile, const char* strMode) ai_assert(strFile != nullptr); ai_assert(strMode != nullptr); FILE* file; -#if defined(_WIN32) && !defined(WindowsStore) +#ifdef _WIN32 file = ::_wfopen(Utf8ToWide(strFile).c_str(), Utf8ToWide(strMode).c_str()); #else file = ::fopen(strFile, strMode); @@ -150,21 +150,12 @@ inline static std::string MakeAbsolutePath(const char* in) ai_assert(in); std::string out; #ifdef _WIN32 -#ifndef WindowsStore wchar_t* ret = ::_wfullpath(nullptr, Utf8ToWide(in).c_str(), 0); if (ret) { out = WideToUtf8(ret); free(ret); } #else - char* ret = ::_fullpath(nullptr, in, 0); - if (ret) { - out = ret; - free(ret); - } -#endif -#else - // use realpath char* ret = realpath(in, nullptr); if (ret) { out = ret; From 873a358ce483c742f502f5b80a3af73ab134425a Mon Sep 17 00:00:00 2001 From: Mike Samsonov Date: Wed, 28 Aug 2019 18:42:49 +0100 Subject: [PATCH 08/12] A crash in the aiMesh descructor --- CMakeLists.txt | 2 +- code/Common/SceneCombiner.cpp | 29 +++++++++++++++++++++++++++++ include/assimp/SceneCombiner.h | 2 ++ test/unit/utglTF2ImportExport.cpp | 9 +++++++++ 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c1517e93c..61251f85a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -253,7 +253,7 @@ ELSEIF(MSVC) IF(MSVC12) ADD_COMPILE_OPTIONS(/wd4351) ENDIF() - SET(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /MDd /Ob2") + SET(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /MDd /Ob2 /DEBUG:FULL /Zi") ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) IF(NOT HUNTER_ENABLED) SET(CMAKE_CXX_FLAGS "-fPIC -std=c++11 ${CMAKE_CXX_FLAGS}") diff --git a/code/Common/SceneCombiner.cpp b/code/Common/SceneCombiner.cpp index e445bd743..4e6bc5b47 100644 --- a/code/Common/SceneCombiner.cpp +++ b/code/Common/SceneCombiner.cpp @@ -1091,6 +1091,35 @@ void SceneCombiner::Copy( aiMesh** _dest, const aiMesh* src ) { aiFace& f = dest->mFaces[i]; GetArrayCopy(f.mIndices,f.mNumIndices); } + + // make a deep copy of all blend shapes + CopyPtrArray(dest->mAnimMeshes, dest->mAnimMeshes, dest->mNumAnimMeshes); +} + +// ------------------------------------------------------------------------------------------------ +void SceneCombiner::Copy(aiAnimMesh** _dest, const aiAnimMesh* src) { + if (nullptr == _dest || nullptr == src) { + return; + } + + aiAnimMesh* dest = *_dest = new aiAnimMesh(); + + // get a flat copy + ::memcpy(dest, src, sizeof(aiAnimMesh)); + + // and reallocate all arrays + GetArrayCopy(dest->mVertices, dest->mNumVertices); + GetArrayCopy(dest->mNormals, dest->mNumVertices); + GetArrayCopy(dest->mTangents, dest->mNumVertices); + GetArrayCopy(dest->mBitangents, dest->mNumVertices); + + unsigned int n = 0; + while (dest->HasTextureCoords(n)) + GetArrayCopy(dest->mTextureCoords[n++], dest->mNumVertices); + + n = 0; + while (dest->HasVertexColors(n)) + GetArrayCopy(dest->mColors[n++], dest->mNumVertices); } // ------------------------------------------------------------------------------------------------ diff --git a/include/assimp/SceneCombiner.h b/include/assimp/SceneCombiner.h index 679a2acea..f69a25f43 100644 --- a/include/assimp/SceneCombiner.h +++ b/include/assimp/SceneCombiner.h @@ -65,6 +65,7 @@ struct aiLight; struct aiMetadata; struct aiBone; struct aiMesh; +struct aiAnimMesh; struct aiAnimation; struct aiNodeAnim; @@ -363,6 +364,7 @@ public: static void Copy (aiMesh** dest, const aiMesh* src); // similar to Copy(): + static void Copy (aiAnimMesh** dest, const aiAnimMesh* src); static void Copy (aiMaterial** dest, const aiMaterial* src); static void Copy (aiTexture** dest, const aiTexture* src); static void Copy (aiAnimation** dest, const aiAnimation* src); diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp index 0ba5226cc..1e8e4af9d 100644 --- a/test/unit/utglTF2ImportExport.cpp +++ b/test/unit/utglTF2ImportExport.cpp @@ -380,4 +380,13 @@ TEST_F( utglTF2ImportExport, exportglTF2FromFileTest ) { EXPECT_TRUE( exporterTest() ); } +TEST_F( utglTF2ImportExport, crash_in_anim_mesh_destructor ) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Sample-Models/AnimatedMorphCube-glTF/AnimatedMorphCube.gltf", + aiProcess_ValidateDataStructure); + ASSERT_NE( nullptr, scene ); + Assimp::Exporter exporter; + ASSERT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "glb2", ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Sample-Models/AnimatedMorphCube-glTF/AnimatedMorphCube_out.glTF")); +} + #endif // ASSIMP_BUILD_NO_EXPORT From 0324643cd5821dc6da7b58bf90c4be3e2d60e111 Mon Sep 17 00:00:00 2001 From: Mike Samsonov Date: Wed, 28 Aug 2019 18:53:13 +0100 Subject: [PATCH 09/12] Missing model files --- .../AnimatedMorphCube.bin | Bin 0 -> 4284 bytes .../AnimatedMorphCube.gltf | 282 ++++++++++++++++++ 2 files changed, 282 insertions(+) create mode 100644 test/models/glTF2/glTF-Sample-Models/AnimatedMorphCube-glTF/AnimatedMorphCube.bin create mode 100644 test/models/glTF2/glTF-Sample-Models/AnimatedMorphCube-glTF/AnimatedMorphCube.gltf diff --git a/test/models/glTF2/glTF-Sample-Models/AnimatedMorphCube-glTF/AnimatedMorphCube.bin b/test/models/glTF2/glTF-Sample-Models/AnimatedMorphCube-glTF/AnimatedMorphCube.bin new file mode 100644 index 0000000000000000000000000000000000000000..7b14a1793452ffe0860fe0ef1f0d7a60187b99d8 GIT binary patch literal 4284 zcmeH~4NOy46vwYn5h?-&)QLJw{X(Lm79C38Jx6VZn++Sf>ck;_R#Y@HKRQ34RY9wp zW}*%|<1&dlt&?Snb4ziW%&B4ZGb%dh&^e7msB^|jrt|H-`yS@SWRAov*%DsT{{B7p zobyiaJ*OXpG+hp8QiL>1A65B3M?0F<94v1$w3LCNy_`>XS)WB<-a?XTAAShZc9N3EOVqxNsn z|KE8z*SMJmijw(vX>;^{`K&wtUix$f)w($~zli^f#5Sk47N6$LR}g8%wkntevF8xd znrKKHMh(%DFcM1IGKP`}(vF0aNXBpyO>`uR#4tvY4x~MaB^?=K`F5{$h6-z)PT`E# z%NR=cxfAJWubJNU&!fyvKX$p8%}pyj9%lE_pL{;H=BF$em_J18bg<3U33}-Du-}~s zLktEu>PdxBCKH_ZnjzC-fg8Ro$hBJGfqxzp*lZBYe*dJI3gLaH6V7@+fEe9I7;o9a z^0=VZw;j6cOJSyUH?aG{U4I!E39lsxv4EJGy?I9fYJc37}2;KBSIKrgC>DCZj?F_{|ZY@@N z!?E5Ufe|_#4lu;v7)yIxXzPd{xjNz3p3eBAuPZ(l^E1jcor~7q0 z;WguJe>!S)8Q9k_7Sk;joNpVC#jXih?wN>}eOcHjW@DUwDjH4Gagx=F4rdOQx@Y5Y zZ!X^Q&%;n%9wr(VpxLqr=hh`Ch4$-U8xdVkre5(h0IFY!CBw4ky8|t1j!!OFo&~Oc?l;WM>q%WxXGFG zMX1ypL=@vW8+N5|Ruqnr?e@8xJB}1`w(YlxGnkZerYC&KdAQ^lrv}e)K90V|X$|^K zwzK||?sM@;8_sosNY2*RI&$_ckLRqN)0&X*6fiw*j&z};dz{dEaE&*-{UL{ES2ru@;Q5!7jRzLXXg|}nQPbC zA-0ZiOB+(sA-zi)-Jg*L=5MCb&(jbxt{2dQ zi9^BVUQdg)gP^8v8;yOK2$ywkswF+3UOY_c;I2@(<$G%1-2s9RUZAdNQE(=umS!&3 zg1OBdx{trzWs}eHf zW`H*NkYJxM3vyR%5iYzj7lh*ZLQP;kROP1%-A65Ce&Iqt!3I^4CyXo3E`dOu!??F` z8N@D*F(w?yhttNQ)YT6PAds_Wn7P6Z?Eiy-{p{sum!zC!iE_rBm9yWj^n}JN_ezq| zLm}C6Z_QGAPEdN$s`ThdrFTavJ#CMXdp%{VJOitg+351EJTrTX Date: Wed, 28 Aug 2019 19:35:13 +0100 Subject: [PATCH 10/12] alloc-dealloc-mismatch --- code/glTF2/glTF2Importer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/glTF2/glTF2Importer.cpp b/code/glTF2/glTF2Importer.cpp index c6e998b3a..bd6a03174 100644 --- a/code/glTF2/glTF2Importer.cpp +++ b/code/glTF2/glTF2Importer.cpp @@ -1041,7 +1041,7 @@ aiNodeAnim* CreateNodeAnim(glTF2::Asset& r, Node& node, AnimationSamplers& sampl delete[] values; } else if (node.rotation.isPresent) { anim->mNumRotationKeys = 1; - anim->mRotationKeys = new aiQuatKey(); + anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys]; anim->mRotationKeys->mTime = 0.f; anim->mRotationKeys->mValue.x = node.rotation.value[0]; anim->mRotationKeys->mValue.y = node.rotation.value[1]; From 4029fe5e4645d6e8f9db26cd260950ec57dd9cb7 Mon Sep 17 00:00:00 2001 From: Mike Samsonov Date: Wed, 28 Aug 2019 20:12:46 +0100 Subject: [PATCH 11/12] alloc-dealloc-mismatch --- code/glTF2/glTF2Importer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/glTF2/glTF2Importer.cpp b/code/glTF2/glTF2Importer.cpp index bd6a03174..a52e43716 100644 --- a/code/glTF2/glTF2Importer.cpp +++ b/code/glTF2/glTF2Importer.cpp @@ -1064,7 +1064,7 @@ aiNodeAnim* CreateNodeAnim(glTF2::Asset& r, Node& node, AnimationSamplers& sampl delete[] values; } else if (node.scale.isPresent) { anim->mNumScalingKeys = 1; - anim->mScalingKeys = new aiVectorKey(); + anim->mScalingKeys = new aiVectorKey[anim->mNumScalingKeys]; anim->mScalingKeys->mTime = 0.f; anim->mScalingKeys->mValue.x = node.scale.value[0]; anim->mScalingKeys->mValue.y = node.scale.value[1]; From b271091c64b3c6e7d17d32e003ecbfb708ba64e5 Mon Sep 17 00:00:00 2001 From: Mike Samsonov Date: Thu, 29 Aug 2019 10:44:56 +0100 Subject: [PATCH 12/12] fix division by zero --- code/glTF2/glTF2Importer.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/glTF2/glTF2Importer.cpp b/code/glTF2/glTF2Importer.cpp index a52e43716..eacf57c89 100644 --- a/code/glTF2/glTF2Importer.cpp +++ b/code/glTF2/glTF2Importer.cpp @@ -1130,6 +1130,7 @@ void glTF2Importer::ImportAnimations(glTF2::Asset& r) // Use the latest keyframe for the duration of the animation double maxDuration = 0; + unsigned int maxNumberOfKeys = 0; for (unsigned int j = 0; j < ai_anim->mNumChannels; ++j) { auto chan = ai_anim->mChannels[j]; if (chan->mNumPositionKeys) { @@ -1137,21 +1138,25 @@ void glTF2Importer::ImportAnimations(glTF2::Asset& r) if (lastPosKey.mTime > maxDuration) { maxDuration = lastPosKey.mTime; } + maxNumberOfKeys = std::max(maxNumberOfKeys, chan->mNumPositionKeys); } if (chan->mNumRotationKeys) { auto lastRotKey = chan->mRotationKeys[chan->mNumRotationKeys - 1]; if (lastRotKey.mTime > maxDuration) { maxDuration = lastRotKey.mTime; } + maxNumberOfKeys = std::max(maxNumberOfKeys, chan->mNumRotationKeys); } if (chan->mNumScalingKeys) { auto lastScaleKey = chan->mScalingKeys[chan->mNumScalingKeys - 1]; if (lastScaleKey.mTime > maxDuration) { maxDuration = lastScaleKey.mTime; } + maxNumberOfKeys = std::max(maxNumberOfKeys, chan->mNumScalingKeys); } } ai_anim->mDuration = maxDuration; + ai_anim->mTicksPerSecond = (maxNumberOfKeys > 0 && maxDuration > 0) ? (maxNumberOfKeys / (maxDuration/1000)) : 30; mScene->mAnimations[i] = ai_anim; }