diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index 0e4ba6eda..37aacd2fb 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -1108,6 +1108,7 @@ public: bool KHR_materials_clearcoat; bool KHR_materials_transmission; bool KHR_draco_mesh_compression; + bool FB_ngon_encoding; } extensionsUsed; //! Keeps info about the required extensions diff --git a/code/AssetLib/glTF2/glTF2AssetWriter.inl b/code/AssetLib/glTF2/glTF2AssetWriter.inl index 166eada0f..aae96d0f7 100644 --- a/code/AssetLib/glTF2/glTF2AssetWriter.inl +++ b/code/AssetLib/glTF2/glTF2AssetWriter.inl @@ -507,6 +507,19 @@ namespace glTF2 { Mesh::Primitive& p = m.primitives[i]; Value prim; prim.SetObject(); + + // Extensions + { + Value exts; + exts.SetObject(); + + Value FB_ngon_encoding; + FB_ngon_encoding.SetObject(); + + exts.AddMember(StringRef("FB_ngon_encoding"), FB_ngon_encoding, w.mAl); + prim.AddMember("extensions", exts, w.mAl); + } + { prim.AddMember("mode", Value(int(p.mode)).Move(), w.mAl); @@ -874,6 +887,10 @@ namespace glTF2 { if (this->mAsset.extensionsUsed.KHR_materials_transmission) { exts.PushBack(StringRef("KHR_materials_transmission"), mAl); } + + if (this->mAsset.extensionsUsed.FB_ngon_encoding) { + exts.PushBack(StringRef("FB_ngon_encoding"), mAl); + } } if (!exts.Empty()) diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index aa89e96da..d244e19f5 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -97,6 +97,9 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai mAsset.reset( new Asset( pIOSystem ) ); + // Always on as our triangulation process is aware of this type of encoding + mAsset->extensionsUsed.FB_ngon_encoding = true; + if (isBinary) { mAsset->SetAsBinary(); } diff --git a/code/PostProcessing/TriangulateProcess.cpp b/code/PostProcessing/TriangulateProcess.cpp index e971bf85f..f8e63c304 100644 --- a/code/PostProcessing/TriangulateProcess.cpp +++ b/code/PostProcessing/TriangulateProcess.cpp @@ -217,10 +217,21 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) // if it's a simple point,line or triangle: just copy it if( face.mNumIndices <= 3) { + // ngon encoding: making sure that triangles are not recognized as false ngons. + // To do so, we make sure the first indice is not the same as previous triangle emitted. + unsigned int prev_first_indice = (unsigned int)-1; + if (curOut != out) prev_first_indice = (curOut - 1)->mIndices[0]; + aiFace& nface = *curOut++; nface.mNumIndices = face.mNumIndices; nface.mIndices = face.mIndices; + if (nface.mIndices[0] == prev_first_indice) { + // rotate indices to avoid ngon encoding false ngons + std::swap(nface.mIndices[0], nface.mIndices[2]); + std::swap(nface.mIndices[1], nface.mIndices[2]); + } + face.mIndices = nullptr; continue; }