From 1f9d6f1ec4b60ce94699ac4f644d472d45e8e71e Mon Sep 17 00:00:00 2001 From: Sebastian Matusik Date: Thu, 26 Apr 2018 17:34:27 +0100 Subject: [PATCH 01/11] Fix for blendshapes import when using the JoinIdenticalVertices optimization flag --- code/JoinVerticesProcess.cpp | 277 ++++++++++++++++++++--------------- include/assimp/Vertex.h | 24 +++ 2 files changed, 179 insertions(+), 122 deletions(-) diff --git a/code/JoinVerticesProcess.cpp b/code/JoinVerticesProcess.cpp index cffe74fb2..cb2d4c1f5 100644 --- a/code/JoinVerticesProcess.cpp +++ b/code/JoinVerticesProcess.cpp @@ -114,6 +114,125 @@ void JoinVerticesProcess::Execute( aiScene* pScene) pScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT; } +namespace { + +bool areVerticesEqual(const Vertex &lhs, const Vertex &rhs, bool complex) +{ + // A little helper to find locally close vertices faster. + // Try to reuse the lookup table from the last step. + const static float epsilon = 1e-5f; + // Squared because we check against squared length of the vector difference + static const float squareEpsilon = epsilon * epsilon; + + // Square compare is useful for animeshes vertexes compare + if ((lhs.position - rhs.position).SquareLength() > squareEpsilon) { + return false; + } + + // We just test the other attributes even if they're not present in the mesh. + // In this case they're initialized to 0 so the comparison succeeds. + // By this method the non-present attributes are effectively ignored in the comparison. + if ((lhs.normal - rhs.normal).SquareLength() > squareEpsilon) { + return false; + } + + if ((lhs.texcoords[0] - rhs.texcoords[0]).SquareLength() > squareEpsilon) { + return false; + } + + if ((lhs.tangent - rhs.tangent).SquareLength() > squareEpsilon) { + return false; + } + + if ((lhs.bitangent - rhs.bitangent).SquareLength() > squareEpsilon) { + return false; + } + + // Usually we won't have vertex colors or multiple UVs, so we can skip from here + // Actually this increases runtime performance slightly, at least if branch + // prediction is on our side. + if (complex) { + for (int i = 0; i < 8; i++) { + if (i > 0 && (lhs.texcoords[i] - rhs.texcoords[i]).SquareLength() > squareEpsilon) { + return false; + } + if (GetColorDifference(lhs.colors[i], rhs.colors[i]) > squareEpsilon) { + return false; + } + } + } + return true; +} + +template +void updateXMeshVertices(XMesh *pMesh, std::vector &uniqueVertices) { + // replace vertex data with the unique data sets + pMesh->mNumVertices = (unsigned int)uniqueVertices.size(); + + // ---------------------------------------------------------------------------- + // NOTE - we're *not* calling Vertex::SortBack() because it would check for + // presence of every single vertex component once PER VERTEX. And our CPU + // dislikes branches, even if they're easily predictable. + // ---------------------------------------------------------------------------- + + // Position, if present (check made for aiAnimMesh) + if (pMesh->mVertices) + { + delete [] pMesh->mVertices; + pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; + for (unsigned int a = 0; a < pMesh->mNumVertices; a++) { + pMesh->mVertices[a] = uniqueVertices[a].position; + } + } + + // Normals, if present + if (pMesh->mNormals) + { + delete [] pMesh->mNormals; + pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; + for( unsigned int a = 0; a < pMesh->mNumVertices; a++) { + pMesh->mNormals[a] = uniqueVertices[a].normal; + } + } + // Tangents, if present + if (pMesh->mTangents) + { + delete [] pMesh->mTangents; + pMesh->mTangents = new aiVector3D[pMesh->mNumVertices]; + for (unsigned int a = 0; a < pMesh->mNumVertices; a++) { + pMesh->mTangents[a] = uniqueVertices[a].tangent; + } + } + // Bitangents as well + if (pMesh->mBitangents) + { + delete [] pMesh->mBitangents; + pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices]; + for (unsigned int a = 0; a < pMesh->mNumVertices; a++) { + pMesh->mBitangents[a] = uniqueVertices[a].bitangent; + } + } + // Vertex colors + for (unsigned int a = 0; pMesh->HasVertexColors(a); a++) + { + delete [] pMesh->mColors[a]; + pMesh->mColors[a] = new aiColor4D[pMesh->mNumVertices]; + for( unsigned int b = 0; b < pMesh->mNumVertices; b++) { + pMesh->mColors[a][b] = uniqueVertices[b].colors[a]; + } + } + // Texture coords + for (unsigned int a = 0; pMesh->HasTextureCoords(a); a++) + { + delete [] pMesh->mTextureCoords[a]; + pMesh->mTextureCoords[a] = new aiVector3D[pMesh->mNumVertices]; + for (unsigned int b = 0; b < pMesh->mNumVertices; b++) { + pMesh->mTextureCoords[a][b] = uniqueVertices[b].texcoords[a]; + } + } +} +} // namespace + // ------------------------------------------------------------------------------------------------ // Unites identical vertices in the given mesh int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) @@ -138,9 +257,6 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) static_assert(AI_MAX_VERTICES == 0x7fffffff, "AI_MAX_VERTICES == 0x7fffffff"); std::vector replaceIndex( pMesh->mNumVertices, 0xffffffff); - // A little helper to find locally close vertices faster. - // Try to reuse the lookup table from the last step. - const static float epsilon = 1e-5f; // float posEpsilonSqr; SpatialSort* vertexFinder = NULL; SpatialSort _vertexFinder; @@ -162,9 +278,6 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) // posEpsilonSqr = ComputePositionEpsilon(pMesh); } - // Squared because we check against squared length of the vector difference - static const float squareEpsilon = epsilon * epsilon; - // Again, better waste some bytes than a realloc ... std::vector verticesFound; verticesFound.reserve(10); @@ -172,6 +285,16 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) // Run an optimized code path if we don't have multiple UVs or vertex colors. // This should yield false in more than 99% of all imports ... const bool complex = ( pMesh->GetNumColorChannels() > 0 || pMesh->GetNumUVChannels() > 1); + const bool hasAnimMeshes = pMesh->mNumAnimMeshes > 0; + + // We'll never have more vertices afterwards. + std::vector> uniqueAnimatedVertices; + if (hasAnimMeshes) { + uniqueAnimatedVertices.resize(pMesh->mNumAnimMeshes); + for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) { + uniqueAnimatedVertices[animMeshIndex].reserve(pMesh->mNumVertices); + } + } // Now check each vertex if it brings something new to the table for( unsigned int a = 0; a < pMesh->mNumVertices; a++) { @@ -184,74 +307,32 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) // check all unique vertices close to the position if this vertex is already present among them for( unsigned int b = 0; b < verticesFound.size(); b++) { - const unsigned int vidx = verticesFound[b]; const unsigned int uidx = replaceIndex[ vidx]; if( uidx & 0x80000000) continue; const Vertex& uv = uniqueVertices[ uidx]; - // Position mismatch is impossible - the vertex finder already discarded all non-matching positions - // We just test the other attributes even if they're not present in the mesh. - // In this case they're initialized to 0 so the comparison succeeds. - // By this method the non-present attributes are effectively ignored in the comparison. - if( (uv.normal - v.normal).SquareLength() > squareEpsilon) - continue; - if( (uv.texcoords[0] - v.texcoords[0]).SquareLength() > squareEpsilon) - continue; - if( (uv.tangent - v.tangent).SquareLength() > squareEpsilon) - continue; - if( (uv.bitangent - v.bitangent).SquareLength() > squareEpsilon) + if (!areVerticesEqual(v, uv, complex)) { continue; + } - // Usually we won't have vertex colors or multiple UVs, so we can skip from here - // Actually this increases runtime performance slightly, at least if branch - // prediction is on our side. - if (complex){ - // manually unrolled because continue wouldn't work as desired in an inner loop, - // also because some compilers seem to fail the task. Colors and UV coords - // are interleaved since the higher entries are most likely to be - // zero and thus useless. By interleaving the arrays, vertices are, - // on average, rejected earlier. - - if( (uv.texcoords[1] - v.texcoords[1]).SquareLength() > squareEpsilon) - continue; - if( GetColorDifference( uv.colors[0], v.colors[0]) > squareEpsilon) - continue; - - if( (uv.texcoords[2] - v.texcoords[2]).SquareLength() > squareEpsilon) - continue; - if( GetColorDifference( uv.colors[1], v.colors[1]) > squareEpsilon) - continue; - - if( (uv.texcoords[3] - v.texcoords[3]).SquareLength() > squareEpsilon) - continue; - if( GetColorDifference( uv.colors[2], v.colors[2]) > squareEpsilon) - continue; - - if( (uv.texcoords[4] - v.texcoords[4]).SquareLength() > squareEpsilon) - continue; - if( GetColorDifference( uv.colors[3], v.colors[3]) > squareEpsilon) - continue; - - if( (uv.texcoords[5] - v.texcoords[5]).SquareLength() > squareEpsilon) - continue; - if( GetColorDifference( uv.colors[4], v.colors[4]) > squareEpsilon) - continue; - - if( (uv.texcoords[6] - v.texcoords[6]).SquareLength() > squareEpsilon) - continue; - if( GetColorDifference( uv.colors[5], v.colors[5]) > squareEpsilon) - continue; - - if( (uv.texcoords[7] - v.texcoords[7]).SquareLength() > squareEpsilon) - continue; - if( GetColorDifference( uv.colors[6], v.colors[6]) > squareEpsilon) - continue; - - if( GetColorDifference( uv.colors[7], v.colors[7]) > squareEpsilon) + if (hasAnimMeshes) { + // If given vertex is animated, then it has to be preserver 1 to 1 (base mesh and animated mesh require same topology) + // NOTE: not doing this totaly breaks anim meshes as they don't have their own faces (they use pMesh->mFaces) + bool breaksAnimMesh = false; + for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) { + const Vertex& animatedUV = uniqueAnimatedVertices[animMeshIndex][ uidx]; + Vertex aniMeshVertex(pMesh->mAnimMeshes[animMeshIndex], a); + if (!areVerticesEqual(aniMeshVertex, animatedUV, complex)) { + breaksAnimMesh = true; + break; + } + } + if (breaksAnimMesh) { continue; + } } // we're still here -> this vertex perfectly matches our given vertex @@ -270,6 +351,12 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) // no unique vertex matches it up to now -> so add it replaceIndex[a] = (unsigned int)uniqueVertices.size(); uniqueVertices.push_back( v); + if (hasAnimMeshes) { + for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) { + Vertex aniMeshVertex(pMesh->mAnimMeshes[animMeshIndex], a); + uniqueAnimatedVertices[animMeshIndex].push_back(aniMeshVertex); + } + } } } @@ -287,64 +374,10 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) )); } - // replace vertex data with the unique data sets - pMesh->mNumVertices = (unsigned int)uniqueVertices.size(); - - // ---------------------------------------------------------------------------- - // NOTE - we're *not* calling Vertex::SortBack() because it would check for - // presence of every single vertex component once PER VERTEX. And our CPU - // dislikes branches, even if they're easily predictable. - // ---------------------------------------------------------------------------- - - // Position - delete [] pMesh->mVertices; - pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; - for( unsigned int a = 0; a < pMesh->mNumVertices; a++) - pMesh->mVertices[a] = uniqueVertices[a].position; - - // Normals, if present - if( pMesh->mNormals) - { - delete [] pMesh->mNormals; - pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; - for( unsigned int a = 0; a < pMesh->mNumVertices; a++) { - pMesh->mNormals[a] = uniqueVertices[a].normal; - } - } - // Tangents, if present - if( pMesh->mTangents) - { - delete [] pMesh->mTangents; - pMesh->mTangents = new aiVector3D[pMesh->mNumVertices]; - for( unsigned int a = 0; a < pMesh->mNumVertices; a++) { - pMesh->mTangents[a] = uniqueVertices[a].tangent; - } - } - // Bitangents as well - if( pMesh->mBitangents) - { - delete [] pMesh->mBitangents; - pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices]; - for( unsigned int a = 0; a < pMesh->mNumVertices; a++) { - pMesh->mBitangents[a] = uniqueVertices[a].bitangent; - } - } - // Vertex colors - for( unsigned int a = 0; pMesh->HasVertexColors(a); a++) - { - delete [] pMesh->mColors[a]; - pMesh->mColors[a] = new aiColor4D[pMesh->mNumVertices]; - for( unsigned int b = 0; b < pMesh->mNumVertices; b++) { - pMesh->mColors[a][b] = uniqueVertices[b].colors[a]; - } - } - // Texture coords - for( unsigned int a = 0; pMesh->HasTextureCoords(a); a++) - { - delete [] pMesh->mTextureCoords[a]; - pMesh->mTextureCoords[a] = new aiVector3D[pMesh->mNumVertices]; - for( unsigned int b = 0; b < pMesh->mNumVertices; b++) { - pMesh->mTextureCoords[a][b] = uniqueVertices[b].texcoords[a]; + updateXMeshVertices(pMesh, uniqueVertices); + if (hasAnimMeshes) { + for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) { + updateXMeshVertices(pMesh->mAnimMeshes[animMeshIndex], uniqueAnimatedVertices[animMeshIndex]); } } diff --git a/include/assimp/Vertex.h b/include/assimp/Vertex.h index 02ae3c0f4..f1c02ee07 100644 --- a/include/assimp/Vertex.h +++ b/include/assimp/Vertex.h @@ -134,6 +134,30 @@ public: } } + // ---------------------------------------------------------------------------- + /** Extract a particular vertex from a anim mesh and interleave all components */ + explicit Vertex(const aiAnimMesh* msh, unsigned int idx) { + ai_assert(idx < msh->mNumVertices); + position = msh->mVertices[idx]; + + if (msh->HasNormals()) { + normal = msh->mNormals[idx]; + } + + if (msh->HasTangentsAndBitangents()) { + tangent = msh->mTangents[idx]; + bitangent = msh->mBitangents[idx]; + } + + for (unsigned int i = 0; msh->HasTextureCoords(i); ++i) { + texcoords[i] = msh->mTextureCoords[i][idx]; + } + + for (unsigned int i = 0; msh->HasVertexColors(i); ++i) { + colors[i] = msh->mColors[i][idx]; + } + } + public: Vertex& operator += (const Vertex& v) { From 1533aec21c4d0aefba4810d2dc9fddf4990ab2a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Korbinian=20W=C3=BCrl?= Date: Fri, 27 Apr 2018 22:11:36 +0200 Subject: [PATCH 02/11] Fix ply exporter to be conformant to spec respecting vertex colors. Vertex colors should be defined as red, green, blue, alpha instead of r, g, b, a and should have the type 'uchar' instead of 'float' --- code/PlyExporter.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/code/PlyExporter.cpp b/code/PlyExporter.cpp index 2d528c96c..31c64a4d1 100644 --- a/code/PlyExporter.cpp +++ b/code/PlyExporter.cpp @@ -194,16 +194,16 @@ PlyExporter::PlyExporter(const char* _filename, const aiScene* pScene, bool bina for (unsigned int n = PLY_EXPORT_HAS_COLORS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_COLOR_SETS; n <<= 1, ++c) { if (!c) { - mOutput << "property " << typeName << " r" << endl; - mOutput << "property " << typeName << " g" << endl; - mOutput << "property " << typeName << " b" << endl; - mOutput << "property " << typeName << " a" << endl; + mOutput << "property " << "uchar" << " red" << endl; + mOutput << "property " << "uchar" << " green" << endl; + mOutput << "property " << "uchar" << " blue" << endl; + mOutput << "property " << "uchar" << " alpha" << endl; } else { - mOutput << "property " << typeName << " r" << c << endl; - mOutput << "property " << typeName << " g" << c << endl; - mOutput << "property " << typeName << " b" << c << endl; - mOutput << "property " << typeName << " a" << c << endl; + mOutput << "property " << "uchar" << " red" << c << endl; + mOutput << "property " << "uchar" << " green" << c << endl; + mOutput << "property " << "uchar" << " blue" << c << endl; + mOutput << "property " << "uchar" << " alpha" << c << endl; } } @@ -288,13 +288,13 @@ void PlyExporter::WriteMeshVerts(const aiMesh* m, unsigned int components) for (unsigned int n = PLY_EXPORT_HAS_COLORS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_COLOR_SETS; n <<= 1, ++c) { if (m->HasVertexColors(c)) { mOutput << - " " << m->mColors[c][i].r << - " " << m->mColors[c][i].g << - " " << m->mColors[c][i].b << - " " << m->mColors[c][i].a; + " " << (int)(m->mColors[c][i].r * 255) << + " " << (int)(m->mColors[c][i].g * 255) << + " " << (int)(m->mColors[c][i].b * 255) << + " " << (int)(m->mColors[c][i].a * 255); } else { - mOutput << " -1.0 -1.0 -1.0 -1.0"; + mOutput << " 0 0 0"; } } From 6fb9ebe3c891f05acccb08e7c89d70077409b2bd Mon Sep 17 00:00:00 2001 From: Trylz Date: Sat, 28 Apr 2018 23:34:07 -0400 Subject: [PATCH 03/11] Apply fix --- code/FBXConverter.cpp | 27 ++++++++++++++++----------- code/FBXConverter.h | 10 +++++----- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 2c9818a16..d6529d119 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -874,7 +874,7 @@ void Converter::ConvertModel( const Model& model, aiNode& nd, const aiMatrix4x4& const MeshGeometry* const mesh = dynamic_cast< const MeshGeometry* >( geo ); if ( mesh ) { - const std::vector& indices = ConvertMesh( *mesh, model, node_global_transform ); + const std::vector& indices = ConvertMesh( *mesh, model, node_global_transform, nd); std::copy( indices.begin(), indices.end(), std::back_inserter( meshes ) ); } else { @@ -891,7 +891,7 @@ void Converter::ConvertModel( const Model& model, aiNode& nd, const aiMatrix4x4& } std::vector Converter::ConvertMesh( const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform ) + const aiMatrix4x4& node_global_transform, aiNode& nd) { std::vector temp; @@ -915,17 +915,17 @@ std::vector Converter::ConvertMesh( const MeshGeometry& mesh, cons const MatIndexArray::value_type base = mindices[ 0 ]; for( MatIndexArray::value_type index : mindices ) { if ( index != base ) { - return ConvertMeshMultiMaterial( mesh, model, node_global_transform ); + return ConvertMeshMultiMaterial( mesh, model, node_global_transform, nd); } } } // faster code-path, just copy the data - temp.push_back( ConvertMeshSingleMaterial( mesh, model, node_global_transform ) ); + temp.push_back( ConvertMeshSingleMaterial( mesh, model, node_global_transform, nd) ); return temp; } -aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh ) +aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh, aiNode& nd) { aiMesh* const out_mesh = new aiMesh(); meshes.push_back( out_mesh ); @@ -940,15 +940,19 @@ aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh ) if ( name.length() ) { out_mesh->mName.Set( name ); } + else + { + out_mesh->mName = nd.mName; + } return out_mesh; } unsigned int Converter::ConvertMeshSingleMaterial( const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform ) + const aiMatrix4x4& node_global_transform, aiNode& nd) { const MatIndexArray& mindices = mesh.GetMaterialIndices(); - aiMesh* const out_mesh = SetupEmptyMesh( mesh ); + aiMesh* const out_mesh = SetupEmptyMesh(mesh, nd); const std::vector& vertices = mesh.GetVertices(); const std::vector& faces = mesh.GetFaceIndexCounts(); @@ -1072,7 +1076,7 @@ unsigned int Converter::ConvertMeshSingleMaterial( const MeshGeometry& mesh, con } std::vector Converter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform ) + const aiMatrix4x4& node_global_transform, aiNode& nd) { const MatIndexArray& mindices = mesh.GetMaterialIndices(); ai_assert( mindices.size() ); @@ -1083,7 +1087,7 @@ std::vector Converter::ConvertMeshMultiMaterial( const MeshGeometr for( MatIndexArray::value_type index : mindices ) { if ( had.find( index ) == had.end() ) { - indices.push_back( ConvertMeshMultiMaterial( mesh, model, index, node_global_transform ) ); + indices.push_back( ConvertMeshMultiMaterial( mesh, model, index, node_global_transform, nd) ); had.insert( index ); } } @@ -1093,9 +1097,10 @@ std::vector Converter::ConvertMeshMultiMaterial( const MeshGeometr unsigned int Converter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model, MatIndexArray::value_type index, - const aiMatrix4x4& node_global_transform ) + const aiMatrix4x4& node_global_transform, + aiNode& nd) { - aiMesh* const out_mesh = SetupEmptyMesh( mesh ); + aiMesh* const out_mesh = SetupEmptyMesh(mesh, nd); const MatIndexArray& mindices = mesh.GetMaterialIndices(); const std::vector& vertices = mesh.GetVertices(); diff --git a/code/FBXConverter.h b/code/FBXConverter.h index 60fd04e2c..71d93d339 100644 --- a/code/FBXConverter.h +++ b/code/FBXConverter.h @@ -172,23 +172,23 @@ private: // ------------------------------------------------------------------------------------------------ // MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed std::vector ConvertMesh(const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform); + const aiMatrix4x4& node_global_transform, aiNode& nd); // ------------------------------------------------------------------------------------------------ - aiMesh* SetupEmptyMesh(const MeshGeometry& mesh); + aiMesh* SetupEmptyMesh(const MeshGeometry& mesh, aiNode& nd); // ------------------------------------------------------------------------------------------------ unsigned int ConvertMeshSingleMaterial(const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform); + const aiMatrix4x4& node_global_transform, aiNode& nd); // ------------------------------------------------------------------------------------------------ std::vector ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform); + const aiMatrix4x4& node_global_transform, aiNode& nd); // ------------------------------------------------------------------------------------------------ unsigned int ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model, MatIndexArray::value_type index, - const aiMatrix4x4& node_global_transform); + const aiMatrix4x4& node_global_transform, aiNode& nd); // ------------------------------------------------------------------------------------------------ static const unsigned int NO_MATERIAL_SEPARATION = /* std::numeric_limits::max() */ From 9e484daa65dc7993d39e89fa612f91b59f43bc2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Korbinian=20W=C3=BCrl?= Date: Mon, 30 Apr 2018 15:51:48 +0200 Subject: [PATCH 04/11] Unit test for Issue #1923: OBJ Exporter can't correctly export vertex colors --- .../models/OBJ/cube_with_vertexcolors_uni.obj | 30 +++++++++++++++++++ test/unit/utObjImportExport.cpp | 18 +++++++++++ 2 files changed, 48 insertions(+) create mode 100644 test/models/OBJ/cube_with_vertexcolors_uni.obj diff --git a/test/models/OBJ/cube_with_vertexcolors_uni.obj b/test/models/OBJ/cube_with_vertexcolors_uni.obj new file mode 100644 index 000000000..c698b9489 --- /dev/null +++ b/test/models/OBJ/cube_with_vertexcolors_uni.obj @@ -0,0 +1,30 @@ +g cube + +v 0.0 0.0 0.0 0.0 0.0 0.0 +v 0.0 0.0 1.0 1.0 0.6 0.3 +v 0.0 1.0 0.0 0.0 0.0 0.0 +v 0.0 1.0 1.0 0.3 0.6 1.0 +v 1.0 0.0 0.0 0.0 0.0 0.0 +v 1.0 0.0 1.0 1.0 0.6 0.3 +v 1.0 1.0 0.0 0.0 0.0 0.0 +v 1.0 1.0 1.0 0.3 0.6 1.0 + +vn 0.0 0.0 1.0 +vn 0.0 0.0 -1.0 +vn 0.0 1.0 0.0 +vn 0.0 -1.0 0.0 +vn 1.0 0.0 0.0 +vn -1.0 0.0 0.0 + +f 1//2 7//2 5//2 +f 1//2 3//2 7//2 +f 1//6 4//6 3//6 +f 1//6 2//6 4//6 +f 3//3 8//3 7//3 +f 3//3 4//3 8//3 +f 5//5 7//5 8//5 +f 5//5 8//5 6//5 +f 1//4 5//4 6//4 +f 1//4 6//4 2//4 +f 2//1 6//1 8//1 +f 2//1 8//1 4//1 \ No newline at end of file diff --git a/test/unit/utObjImportExport.cpp b/test/unit/utObjImportExport.cpp index 8aec9c443..e879c350e 100644 --- a/test/unit/utObjImportExport.cpp +++ b/test/unit/utObjImportExport.cpp @@ -267,6 +267,24 @@ TEST_F( utObjImportExport, issue809_vertex_color_Test ) { #endif // ASSIMP_BUILD_NO_EXPORT } +TEST_F( utObjImportExport, issue1923_vertex_color_Test ) { + ::Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/cube_with_vertexcolors_uni.obj", aiProcess_ValidateDataStructure ); + EXPECT_NE( nullptr, scene ); + +#ifndef ASSIMP_BUILD_NO_EXPORT + ::Assimp::Exporter exporter; + const aiExportDataBlob* blob = exporter.ExportToBlob( scene, "obj"); + EXPECT_NE( nullptr, blob ); + + const aiScene *sceneReImport = importer.ReadFileFromMemory( blob->data, blob->size, aiProcess_ValidateDataStructure ); + EXPECT_NE( nullptr, scene ); + + SceneDiffer differ; + EXPECT_TRUE( differ.isEqual( scene, sceneReImport ) ); +#endif // ASSIMP_BUILD_NO_EXPORT +} + TEST_F( utObjImportExport, issue1453_segfault ) { static const std::string ObjModel = "v 0.0 0.0 0.0\n" From 9cfdb8d3658f306163d2eb33eaaeb16c5a2eb429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Korbinian=20W=C3=BCrl?= Date: Mon, 30 Apr 2018 16:23:29 +0200 Subject: [PATCH 05/11] Fixed test .obj file: OBJ Vertex Colors are expected to be floats 0-1 See https://github.com/cnr-isti-vclab/vcglib/blob/master/wrap/io_trimesh/import_obj.h#L326 --- test/models/OBJ/cube_with_vertexcolors.obj | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/models/OBJ/cube_with_vertexcolors.obj b/test/models/OBJ/cube_with_vertexcolors.obj index d78d3a555..1541e0823 100644 --- a/test/models/OBJ/cube_with_vertexcolors.obj +++ b/test/models/OBJ/cube_with_vertexcolors.obj @@ -1,13 +1,13 @@ g cube -v 0.0 0.0 0.0 124 110 120 -v 0.0 0.0 1.0 24 0 121 -v 0.0 1.0 0.0 4 0 44 -v 0.0 1.0 1.0 224 0 10 -v 1.0 0.0 0.0 24 200 25 -v 1.0 0.0 1.0 124 10 56 -v 1.0 1.0 0.0 78 10 50 -v 1.0 1.0 1.0 23 0 200 +v 0.0 0.0 0.0 0.48627 0.43137 0.47059 +v 0.0 0.0 1.0 0.09412 0.00000 0.47451 +v 0.0 1.0 0.0 0.01569 0.00000 0.17255 +v 0.0 1.0 1.0 0.87843 0.00000 0.03922 +v 1.0 0.0 0.0 0.09412 0.78431 0.09804 +v 1.0 0.0 1.0 0.48627 0.03922 0.21961 +v 1.0 1.0 0.0 0.30588 0.03922 0.19608 +v 1.0 1.0 1.0 0.09020 0.00000 0.78431 vn 0.0 0.0 1.0 vn 0.0 0.0 -1.0 From 4b7b692e5e72f70ae001a274ccd78a4ffde35d9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Korbinian=20W=C3=BCrl?= Date: Mon, 30 Apr 2018 16:27:34 +0200 Subject: [PATCH 06/11] Fix Issue #1923: OBJ Exporter can't correctly export vertex colors The indexMap for vertices now uses a combined vp + vc index --- code/ObjExporter.cpp | 90 ++++++++++------------------------------ code/ObjExporter.h | 99 +++++++++++++++++++++++++------------------- 2 files changed, 78 insertions(+), 111 deletions(-) diff --git a/code/ObjExporter.cpp b/code/ObjExporter.cpp index 6cd69f402..1542efebf 100644 --- a/code/ObjExporter.cpp +++ b/code/ObjExporter.cpp @@ -114,14 +114,13 @@ static const std::string MaterialExt = ".mtl"; ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMtl) : filename(_filename) , pScene(pScene) -, vp() , vn() , vt() -, vc() -, mVpMap() +, vp() +, useVc(false) , mVnMap() , mVtMap() -, mVcMap() +, mVpMap() , mMeshes() , endl("\n") { // make sure that all formatting happens using the standard, C locale and not the user's current locale @@ -268,27 +267,22 @@ void ObjExporter::WriteGeometryFile(bool noMtl) { AddNode(pScene->mRootNode, mBase); // write vertex positions with colors, if any - mVpMap.getVectors( vp ); - mVcMap.getColors( vc ); - if ( vc.empty() ) { + mVpMap.getKeys( vp ); + if ( !useVc ) { mOutput << "# " << vp.size() << " vertex positions" << endl; - for ( const aiVector3D& v : vp ) { - mOutput << "v " << v.x << " " << v.y << " " << v.z << endl; + for ( const vertexData& v : vp ) { + mOutput << "v " << v.vp.x << " " << v.vp.y << " " << v.vp.z << endl; } } else { mOutput << "# " << vp.size() << " vertex positions and colors" << endl; - size_t colIdx = 0; - for ( const aiVector3D& v : vp ) { - if ( colIdx < vc.size() ) { - mOutput << "v " << v.x << " " << v.y << " " << v.z << " " << vc[ colIdx ].r << " " << vc[ colIdx ].g << " " << vc[ colIdx ].b << endl; - } - ++colIdx; + for ( const vertexData& v : vp ) { + mOutput << "v " << v.vp.x << " " << v.vp.y << " " << v.vp.z << " " << v.vc.r << " " << v.vc.g << " " << v.vc.b << endl; } } mOutput << endl; // write uv coordinates - mVtMap.getVectors(vt); + mVtMap.getKeys(vt); mOutput << "# " << vt.size() << " UV coordinates" << endl; for(const aiVector3D& v : vt) { mOutput << "vt " << v.x << " " << v.y << " " << v.z << endl; @@ -296,7 +290,7 @@ void ObjExporter::WriteGeometryFile(bool noMtl) { mOutput << endl; // write vertex normals - mVnMap.getVectors(vn); + mVnMap.getKeys(vn); mOutput << "# " << vn.size() << " vertex normals" << endl; for(const aiVector3D& v : vn) { mOutput << "vn " << v.x << " " << v.y << " " << v.z << endl; @@ -337,54 +331,15 @@ void ObjExporter::WriteGeometryFile(bool noMtl) { } } -// ------------------------------------------------------------------------------------------------ -int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec) { - vecIndexMap::dataType::iterator vertIt = vecMap.find(vec); - // vertex already exists, so reference it - if(vertIt != vecMap.end()){ - return vertIt->second; - } - vecMap[vec] = mNextIndex; - int ret = mNextIndex; - mNextIndex++; - return ret; -} - -// ------------------------------------------------------------------------------------------------ -void ObjExporter::vecIndexMap::getVectors( std::vector& vecs ) { - vecs.resize(vecMap.size()); - for(vecIndexMap::dataType::iterator it = vecMap.begin(); it != vecMap.end(); ++it){ - vecs[it->second-1] = it->first; - } -} - -// ------------------------------------------------------------------------------------------------ -int ObjExporter::colIndexMap::getIndex( const aiColor4D& col ) { - colIndexMap::dataType::iterator vertIt = colMap.find( col ); - // vertex already exists, so reference it - if ( vertIt != colMap.end() ) { - return vertIt->second; - } - colMap[ col ] = mNextIndex; - int ret = mNextIndex; - mNextIndex++; - - return ret; -} - -// ------------------------------------------------------------------------------------------------ -void ObjExporter::colIndexMap::getColors( std::vector &colors ) { - colors.resize( colMap.size() ); - for ( colIndexMap::dataType::iterator it = colMap.begin(); it != colMap.end(); ++it ) { - colors[ it->second - 1 ] = it->first; - } -} - // ------------------------------------------------------------------------------------------------ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) { mMeshes.push_back(MeshInstance() ); MeshInstance& mesh = mMeshes.back(); + if ( nullptr != m->mColors[ 0 ] ) { + useVc = true; + } + mesh.name = std::string( name.data, name.length ); mesh.matname = GetMaterialName(m->mMaterialIndex); @@ -410,7 +365,13 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4 const unsigned int idx = f.mIndices[a]; aiVector3D vert = mat * m->mVertices[idx]; - face.indices[a].vp = mVpMap.getIndex(vert); + + if ( nullptr != m->mColors[ 0 ] ) { + aiColor4D col4 = m->mColors[ 0 ][ idx ]; + face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(col4.r, col4.g, col4.b)}); + } else { + face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(0,0,0)}); + } if (m->mNormals) { aiVector3D norm = aiMatrix3x3(mat) * m->mNormals[idx]; @@ -419,13 +380,6 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4 face.indices[a].vn = 0; } - if ( nullptr != m->mColors[ 0 ] ) { - aiColor4D col4 = m->mColors[ 0 ][ idx ]; - face.indices[ a ].vc = mVcMap.getIndex( col4 ); - } else { - face.indices[ a ].vc = 0; - } - if ( m->mTextureCoords[ 0 ] ) { face.indices[a].vt = mVtMap.getIndex(m->mTextureCoords[0][idx]); } else { diff --git a/code/ObjExporter.h b/code/ObjExporter.h index 7920598d0..bd745b593 100644 --- a/code/ObjExporter.h +++ b/code/ObjExporter.h @@ -77,13 +77,12 @@ private: FaceVertex() : vp() , vn() - , vt() - , vc() { + , vt() { // empty } // one-based, 0 means: 'does not exist' - unsigned int vp, vn, vt, vc; + unsigned int vp, vn, vt; }; struct Face { @@ -106,66 +105,80 @@ private: private: std::string filename; const aiScene* const pScene; - std::vector vp, vn, vt; + + struct vertexData { + aiVector3D vp; + aiColor3D vc; // OBJ does not support 4D color + }; + + std::vector vn, vt; std::vector vc; + std::vector vp; + bool useVc; - struct aiVectorCompare { - bool operator() (const aiVector3D& a, const aiVector3D& b) const { - if(a.x < b.x) return true; - if(a.x > b.x) return false; - if(a.y < b.y) return true; - if(a.y > b.y) return false; - if(a.z < b.z) return true; + struct vertexDataCompare { + bool operator() ( const vertexData& a, const vertexData& b ) const { + // position + if (a.vp.x < b.vp.x) return true; + if (a.vp.x > b.vp.x) return false; + if (a.vp.y < b.vp.y) return true; + if (a.vp.y > b.vp.y) return false; + if (a.vp.z < b.vp.z) return true; + if (a.vp.z > b.vp.z) return false; + + // color + if (a.vc.r < b.vc.r) return true; + if (a.vc.r > b.vc.r) return false; + if (a.vc.g < b.vc.g) return true; + if (a.vc.g > b.vc.g) return false; + if (a.vc.b < b.vc.b) return true; + if (a.vc.b > b.vc.b) return false; return false; } }; - struct aiColor4Compare { - bool operator() ( const aiColor4D& a, const aiColor4D& b ) const { - if ( a.r < b.r ) return true; - if ( a.r > b.r ) return false; - if ( a.g < b.g ) return true; - if ( a.g > b.g ) return false; - if ( a.b < b.b ) return true; - if ( a.b > b.b ) return false; - if ( a.a < b.a ) return true; - if ( a.a > b.a ) return false; + struct aiVectorCompare { + bool operator() (const aiVector3D& a, const aiVector3D& b) const { + if(a.x < b.x) return true; + if(a.x > b.x) return false; + if(a.y < b.y) return true; + if(a.y > b.y) return false; + if(a.z < b.z) return true; return false; } }; - class vecIndexMap { + template > + class indexMap { int mNextIndex; - typedef std::map dataType; + typedef std::map dataType; dataType vecMap; public: - vecIndexMap() + indexMap() : mNextIndex(1) { // empty } - int getIndex(const aiVector3D& vec); - void getVectors( std::vector& vecs ); + int getIndex(const T& key) { + typename dataType::iterator vertIt = vecMap.find(key); + // vertex already exists, so reference it + if(vertIt != vecMap.end()){ + return vertIt->second; + } + return vecMap[key] = mNextIndex++; + }; + + void getKeys( std::vector& keys ) { + keys.resize(vecMap.size()); + for(typename dataType::iterator it = vecMap.begin(); it != vecMap.end(); ++it){ + keys[it->second-1] = it->first; + } + }; }; - class colIndexMap { - int mNextIndex; - typedef std::map dataType; - dataType colMap; - - public: - colIndexMap() - : mNextIndex( 1 ) { - // empty - } - - int getIndex( const aiColor4D& col ); - void getColors( std::vector &colors ); - }; - - vecIndexMap mVpMap, mVnMap, mVtMap; - colIndexMap mVcMap; + indexMap mVnMap, mVtMap; + indexMap mVpMap; std::vector mMeshes; // this endl() doesn't flush() the stream From 22475130649c3d356c507a7a420ce176d0b45d38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Korbinian=20W=C3=BCrl?= Date: Tue, 1 May 2018 11:23:38 +0200 Subject: [PATCH 07/11] Fix for TravisCI --- test/unit/utObjImportExport.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/unit/utObjImportExport.cpp b/test/unit/utObjImportExport.cpp index e879c350e..5a10ae17b 100644 --- a/test/unit/utObjImportExport.cpp +++ b/test/unit/utObjImportExport.cpp @@ -272,6 +272,8 @@ TEST_F( utObjImportExport, issue1923_vertex_color_Test ) { const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/cube_with_vertexcolors_uni.obj", aiProcess_ValidateDataStructure ); EXPECT_NE( nullptr, scene ); + scene = importer.GetOrphanedScene(); + #ifndef ASSIMP_BUILD_NO_EXPORT ::Assimp::Exporter exporter; const aiExportDataBlob* blob = exporter.ExportToBlob( scene, "obj"); @@ -283,6 +285,8 @@ TEST_F( utObjImportExport, issue1923_vertex_color_Test ) { SceneDiffer differ; EXPECT_TRUE( differ.isEqual( scene, sceneReImport ) ); #endif // ASSIMP_BUILD_NO_EXPORT + + delete scene; } TEST_F( utObjImportExport, issue1453_segfault ) { From ed860230169d4c0ed2d7fa2a303b190da4b07c20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Fricoteaux?= Date: Wed, 2 May 2018 16:13:17 +0200 Subject: [PATCH 08/11] Change glTF2 file extensions from gltf2/glb2 to gltf/glb in the exporter so that it matches the importer and respect the standard specifications --- code/Exporter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/Exporter.cpp b/code/Exporter.cpp index bd533f3b3..894c00740 100644 --- a/code/Exporter.cpp +++ b/code/Exporter.cpp @@ -154,9 +154,9 @@ Exporter::ExportFormatEntry gExporters[] = aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ), Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB, aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ), - Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf2", &ExportSceneGLTF2, + Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf", &ExportSceneGLTF2, aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ), - Exporter::ExportFormatEntry( "glb2", "GL Transmission Format v. 2 (binary)", "glb2", &ExportSceneGLB2, + Exporter::ExportFormatEntry( "glb2", "GL Transmission Format v. 2 (binary)", "glb", &ExportSceneGLB2, aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ), #endif From a0bf664695dd9a4ec46b7a136cdef2003d690056 Mon Sep 17 00:00:00 2001 From: kimkulling Date: Wed, 2 May 2018 16:42:22 +0200 Subject: [PATCH 09/11] closes code/SortByPTypeProcess.cpp: fix memory leak. --- code/SortByPTypeProcess.cpp | 41 +++++++++++++++---------------------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/code/SortByPTypeProcess.cpp b/code/SortByPTypeProcess.cpp index ee18585e2..b67da5b95 100644 --- a/code/SortByPTypeProcess.cpp +++ b/code/SortByPTypeProcess.cpp @@ -85,8 +85,6 @@ void SortByPTypeProcess::SetupProperties(const Importer* pImp) // Update changed meshes in all nodes void UpdateNodes(const std::vector& replaceMeshIndex, aiNode* node) { -// std::vector::const_iterator it; - if (node->mNumMeshes) { unsigned int newSize = 0; @@ -133,10 +131,8 @@ void UpdateNodes(const std::vector& replaceMeshIndex, aiNode* node // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void SortByPTypeProcess::Execute( aiScene* pScene) -{ - if (!pScene->mNumMeshes) - { +void SortByPTypeProcess::Execute( aiScene* pScene) { + if ( 0 == pScene->mNumMeshes) { ASSIMP_LOG_DEBUG("SortByPTypeProcess skipped, there are no meshes"); return; } @@ -152,42 +148,38 @@ void SortByPTypeProcess::Execute( aiScene* pScene) std::vector replaceMeshIndex(pScene->mNumMeshes*4,UINT_MAX); std::vector::iterator meshIdx = replaceMeshIndex.begin(); - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - { + for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { aiMesh* const mesh = pScene->mMeshes[i]; ai_assert(0 != mesh->mPrimitiveTypes); // if there's just one primitive type in the mesh there's nothing to do for us unsigned int num = 0; - if (mesh->mPrimitiveTypes & aiPrimitiveType_POINT) - { + if (mesh->mPrimitiveTypes & aiPrimitiveType_POINT) { ++aiNumMeshesPerPType[0]; ++num; } - if (mesh->mPrimitiveTypes & aiPrimitiveType_LINE) - { + if (mesh->mPrimitiveTypes & aiPrimitiveType_LINE) { ++aiNumMeshesPerPType[1]; ++num; } - if (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE) - { + if (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE) { ++aiNumMeshesPerPType[2]; ++num; } - if (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON) - { + if (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON) { ++aiNumMeshesPerPType[3]; ++num; } - if (1 == num) - { - if (!(configRemoveMeshes & mesh->mPrimitiveTypes)) - { - *meshIdx = (unsigned int) outMeshes.size(); + if (1 == num) { + if (!(configRemoveMeshes & mesh->mPrimitiveTypes)) { + *meshIdx = static_cast( outMeshes.size() ); outMeshes.push_back(mesh); + } else { + delete mesh; + pScene->mMeshes[ i ] = nullptr; + bAnyChanges = true; } - else bAnyChanges = true; meshIdx += 4; continue; @@ -195,14 +187,13 @@ void SortByPTypeProcess::Execute( aiScene* pScene) bAnyChanges = true; // reuse our current mesh arrays for the submesh - // with the largest numer of primitives + // with the largest number of primitives unsigned int aiNumPerPType[4] = {0,0,0,0}; aiFace* pFirstFace = mesh->mFaces; aiFace* const pLastFace = pFirstFace + mesh->mNumFaces; unsigned int numPolyVerts = 0; - for (;pFirstFace != pLastFace; ++pFirstFace) - { + for (;pFirstFace != pLastFace; ++pFirstFace) { if (pFirstFace->mNumIndices <= 3) ++aiNumPerPType[pFirstFace->mNumIndices-1]; else From 4aaf7ad5474c14affaa4d6971d7a9ff6c538173b Mon Sep 17 00:00:00 2001 From: Alexis Breust Date: Thu, 3 May 2018 11:07:39 +0200 Subject: [PATCH 10/11] Added name to nodes --- code/glTF2Exporter.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index fcf8005ae..bd33848d9 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -759,7 +759,7 @@ void glTF2Exporter::ExportMeshes() if (c) p.attributes.color.push_back(c); } - + /*************** Vertices indices ****************/ if (aim->mNumFaces > 0) { std::vector indices; @@ -891,6 +891,8 @@ unsigned int glTF2Exporter::ExportNodeHierarchy(const aiNode* n) { Ref node = mAsset->nodes.Create(mAsset->FindUniqueID(n->mName.C_Str(), "node")); + node->name = n->mName.C_Str(); + if (!n->mTransformation.IsIdentity()) { node->matrix.isPresent = true; CopyValue(n->mTransformation, node->matrix.value); From 908ef3e44ad37c087724553943aacb86f5f3804c Mon Sep 17 00:00:00 2001 From: Eugene Barnett Date: Sat, 5 May 2018 16:57:59 -0400 Subject: [PATCH 11/11] 1740 Issue - Enabling and Disabling importers -ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT will be respected by the macro --using local variable ASSIMP_IMPORTER_ENABLED to include or exclude --an importer -Fixes individual importer ex: set(ASSIMP_BUILD_FBX_IMPORTER OFF) -ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT is cached --if assimp is a child cmake project, need to force cache --from parent project --ex: set(ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT CACHE INTERNAL FALSE) --- code/CMakeLists.txt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index d5d05db18..c8cc2fecd 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -208,8 +208,15 @@ OPTION(ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT "default value of all ASSIMP_BUILD_ # macro to add the CMake Option ADD_ASSIMP_IMPORTER_ which enables compile of loader # this way selective loaders can be compiled (reduces filesize + compile time) MACRO(ADD_ASSIMP_IMPORTER name) - OPTION(ASSIMP_BUILD_${name}_IMPORTER "build the ${name} importer" ${ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT}) - IF(ASSIMP_BUILD_${name}_IMPORTER) + IF (ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT) + set(ASSIMP_IMPORTER_ENABLED TRUE) + IF (DEFINED ASSIMP_BUILD_${name}_IMPORTER AND NOT ASSIMP_BUILD_${name}_IMPORTER) + set(ASSIMP_IMPORTER_ENABLED FALSE) + ENDIF () + ELSE () + set(ASSIMP_IMPORTER_ENABLED ${ASSIMP_BUILD_${name}_IMPORTER}) + ENDIF () + IF (ASSIMP_IMPORTER_ENABLED) LIST(APPEND ASSIMP_LOADER_SRCS ${ARGN}) SET(ASSIMP_IMPORTERS_ENABLED "${ASSIMP_IMPORTERS_ENABLED} ${name}") SET(${name}_SRCS ${ARGN})