From 37e477d3e7ed5af91eaa4e71ed2e12bc8a9c89ec Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 25 Sep 2023 12:23:53 +0200 Subject: [PATCH] Import: fixes #8666: Enable support to read glTF files --- src/Mod/Import/App/AppImportPy.cpp | 5 ++ src/Mod/Import/App/ReaderGltf.cpp | 80 +++++++++++++++++++++++++++ src/Mod/Import/App/ReaderGltf.h | 24 +++++++- src/Mod/Import/Gui/AppImportGuiPy.cpp | 9 ++- src/Mod/Import/Init.py | 1 + 5 files changed, 117 insertions(+), 2 deletions(-) diff --git a/src/Mod/Import/App/AppImportPy.cpp b/src/Mod/Import/App/AppImportPy.cpp index 861d97af23..a5ad694a30 100644 --- a/src/Mod/Import/App/AppImportPy.cpp +++ b/src/Mod/Import/App/AppImportPy.cpp @@ -73,6 +73,7 @@ #include #include "ImportOCAF2.h" +#include "ReaderGltf.h" #include "WriterGltf.h" namespace Import @@ -248,6 +249,10 @@ private: pcDoc->recompute(); } } + else if (file.hasExtension({"glb", "gltf"})) { + Import::ReaderGltf reader(file); + reader.read(hDoc); + } else { throw Py::Exception(PyExc_IOError, "no supported file format"); } diff --git a/src/Mod/Import/App/ReaderGltf.cpp b/src/Mod/Import/App/ReaderGltf.cpp index 81fdc35264..a32b2f42dc 100644 --- a/src/Mod/Import/App/ReaderGltf.cpp +++ b/src/Mod/Import/App/ReaderGltf.cpp @@ -24,9 +24,89 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include +#include +#include +#include +#include +#if OCC_VERSION_HEX >= 0x070500 +#include +#include +#endif #endif #include "ReaderGltf.h" +#include +#include +#include using namespace Import; + +ReaderGltf::ReaderGltf(const Base::FileInfo& file) // NOLINT + : file {file} +{} + +void ReaderGltf::read(Handle(TDocStd_Document) hDoc) // NOLINT +{ +#if OCC_VERSION_HEX >= 0x070500 + const double unit = 0.001; // mm + RWGltf_CafReader aReader; + aReader.SetSystemLengthUnit(unit); + aReader.SetSystemCoordinateSystem(RWMesh_CoordinateSystem_Zup); + aReader.SetDocument(hDoc); + aReader.SetParallel(true); + + TCollection_AsciiString filename(file.filePath().c_str()); + Standard_Boolean ret = aReader.Perform(filename, Message_ProgressRange()); + if (!ret) { + std::stringstream str; + str << "Cannot read from file '" + << "" << file.filePath() << "'"; + } + + Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(hDoc->Main()); + TDF_LabelSequence labels; + aShapeTool->GetShapes(labels); + for (Standard_Integer i = 1; i <= labels.Length(); i++) { + auto label = labels.Value(i); + TopoDS_Shape shape = aShapeTool->GetShape(label); + if (!shape.IsNull()) { + aShapeTool->SetShape(label, fixShape(shape)); + } + } + +#else + throw Base::RuntimeError("gITF support requires OCCT 7.5.0 or later"); +#endif +} + +bool ReaderGltf::cleanup() const +{ + return clean; +} + +void ReaderGltf::setCleanup(bool value) +{ + clean = value; +} + +TopoDS_Shape ReaderGltf::fixShape(TopoDS_Shape shape) // NOLINT +{ + // The glTF reader creates a compound of faces that only contains the triangulation + // but not the underlying surfaces. This leads to faces without boundaries. + // The triangulation is used to create a valid shape. + const double tolerance = 0.5; + std::vector points; + std::vector facets; + Part::TopoShape sh(shape); + sh.getFaces(points, facets, tolerance); + sh.setFaces(points, facets, tolerance); + + if (cleanup()) { + sh.sewShape(); + return sh.removeSplitter(); + } + + return sh.getShape(); +} diff --git a/src/Mod/Import/App/ReaderGltf.h b/src/Mod/Import/App/ReaderGltf.h index 7269351d46..5925100bba 100644 --- a/src/Mod/Import/App/ReaderGltf.h +++ b/src/Mod/Import/App/ReaderGltf.h @@ -24,9 +24,31 @@ #ifndef IMPORT_READER_GLTF_H #define IMPORT_READER_GLTF_H +#include +#include +#include +#include + namespace Import { -} +class ImportExport ReaderGltf +{ +public: + explicit ReaderGltf(const Base::FileInfo& file); + + void read(Handle(TDocStd_Document) hDoc); + bool cleanup() const; + void setCleanup(bool); + +private: + TopoDS_Shape fixShape(TopoDS_Shape); + +private: + Base::FileInfo file; + bool clean = true; +}; + +} // namespace Import #endif // IMPORT_READER_GLTF_H diff --git a/src/Mod/Import/Gui/AppImportGuiPy.cpp b/src/Mod/Import/Gui/AppImportGuiPy.cpp index 58fa4ba5ca..0228cdb37f 100644 --- a/src/Mod/Import/Gui/AppImportGuiPy.cpp +++ b/src/Mod/Import/Gui/AppImportGuiPy.cpp @@ -104,6 +104,7 @@ #include #include #include +#include #include #include #include @@ -523,6 +524,10 @@ private: pcDoc->recompute(); } } + else if (file.hasExtension({"glb", "gltf"})) { + Import::ReaderGltf reader(file); + reader.read(hDoc); + } else { throw Py::Exception(PyExc_IOError, "no supported file format"); } @@ -537,7 +542,9 @@ private: if (useLinkGroup != Py_None) { ocaf.setUseLinkGroup(Base::asBoolean(useLinkGroup)); } - ocaf.setMode(mode); + if (mode >= 0) { + ocaf.setMode(mode); + } auto ret = ocaf.loadShapes(); hApp->Close(hDoc); FC_DURATION_PLUS(d2, t); diff --git a/src/Mod/Import/Init.py b/src/Mod/Import/Init.py index 658ca17173..d2f7fd97f9 100644 --- a/src/Mod/Import/Init.py +++ b/src/Mod/Import/Init.py @@ -31,5 +31,6 @@ # FreeCAD.addExportType("IGES files (*.iges *.igs)","ImportGui") FreeCAD.addImportType("PLMXML files (*.plmxml)", "PlmXmlParser") FreeCAD.addImportType("STEPZ Zip File Type (*.stpZ *.stpz)", "stepZ") +FreeCAD.addImportType("glTF (*.gltf *.glb)", "ImportGui") FreeCAD.addExportType("STEPZ zip File Type (*.stpZ *.stpz)", "stepZ") FreeCAD.addExportType("glTF (*.gltf *.glb)", "ImportGui")