From 5cc7cbea8b673b35054d3d35612d4c3b0a5458bb Mon Sep 17 00:00:00 2001 From: ika Date: Mon, 30 Sep 2024 12:12:05 +0100 Subject: [PATCH] Data Exchange, Gltf Export - Metadata support #79 Add supporting of metadata key-value export into extras section of each node. --- src/RWGltf/RWGltf_CafWriter.cxx | 112 +++++++++++++++++++++++++++++++ src/RWGltf/RWGltf_CafWriter.hxx | 5 ++ tests/metadata/gltf_export/A1 | 3 + tests/metadata/gltf_export/A2 | 3 + tests/metadata/gltf_export/A3 | 3 + tests/metadata/gltf_export/A4 | 3 + tests/metadata/gltf_export/A5 | 3 + tests/metadata/gltf_export/A6 | 3 + tests/metadata/gltf_export/A7 | 3 + tests/metadata/gltf_export/A8 | 3 + tests/metadata/gltf_export/A9 | 3 + tests/metadata/gltf_export/begin | 1 + tests/metadata/gltf_export/end | 39 +++++++++++ tests/metadata/grids.list | 1 + tests/metadata/{ => step}/end | 0 15 files changed, 185 insertions(+) create mode 100644 tests/metadata/gltf_export/A1 create mode 100644 tests/metadata/gltf_export/A2 create mode 100644 tests/metadata/gltf_export/A3 create mode 100644 tests/metadata/gltf_export/A4 create mode 100644 tests/metadata/gltf_export/A5 create mode 100644 tests/metadata/gltf_export/A6 create mode 100644 tests/metadata/gltf_export/A7 create mode 100644 tests/metadata/gltf_export/A8 create mode 100644 tests/metadata/gltf_export/A9 create mode 100644 tests/metadata/gltf_export/begin create mode 100644 tests/metadata/gltf_export/end rename tests/metadata/{ => step}/end (100%) diff --git a/src/RWGltf/RWGltf_CafWriter.cxx b/src/RWGltf/RWGltf_CafWriter.cxx index aa86708d39..e7ef51e957 100644 --- a/src/RWGltf/RWGltf_CafWriter.cxx +++ b/src/RWGltf/RWGltf_CafWriter.cxx @@ -1978,6 +1978,8 @@ void RWGltf_CafWriter::writeNodes (const Handle(TDocStd_Document)& theDocument, #ifdef HAVE_RAPIDJSON Standard_ProgramError_Raise_if (myWriter.get() == NULL, "Internal error: RWGltf_CafWriter::writeNodes()"); + Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDocument->Main()); + // Prepare full indexed map of scene nodes in correct order. RWGltf_GltfSceneNodeMap aSceneNodeMapWithChildren; // indexes starting from 1 for (XCAFPrs_DocumentExplorer aDocExplorer (theDocument, theRootLabels, XCAFPrs_DocumentExplorerFlags_None); @@ -2130,6 +2132,18 @@ void RWGltf_CafWriter::writeNodes (const Handle(TDocStd_Document)& theDocument, myWriter->String (aNodeName.ToCString()); } } + { + Handle(TDataStd_NamedData) aNamedData = aShapeTool->GetNamedProperties(aDocNode.Label); + Handle(TDataStd_NamedData) aRefNamedData = aShapeTool->GetNamedProperties(aDocNode.RefLabel); + if (!aNamedData.IsNull() || !aRefNamedData.IsNull()) + { + myWriter->Key("extras"); + myWriter->StartObject(); + writeExtrasAttributes(aNamedData); + writeExtrasAttributes(aRefNamedData); + myWriter->EndObject(); + } + } myWriter->EndObject(); } myWriter->EndArray(); @@ -2142,6 +2156,104 @@ void RWGltf_CafWriter::writeNodes (const Handle(TDocStd_Document)& theDocument, #endif } +// ======================================================================= +// function : writeExtrasAttributes +// purpose : +// ======================================================================= +void RWGltf_CafWriter::writeExtrasAttributes(const Handle(TDataStd_NamedData)& theNamedData) +{ +#ifdef HAVE_RAPIDJSON + Standard_ProgramError_Raise_if(myWriter.get() == NULL, "Internal error: RWGltf_CafWriter::writeExtrasAttributes()"); + + if (theNamedData.IsNull()) + return; + theNamedData->LoadDeferredData(); + if (theNamedData->HasIntegers()) + { + const TColStd_DataMapOfStringInteger& anIntProperties = theNamedData->GetIntegersContainer(); + for (TColStd_DataMapIteratorOfDataMapOfStringInteger anIter(anIntProperties); + anIter.More(); anIter.Next()) + { + TCollection_AsciiString aKey(anIter.Key()); + myWriter->Key(aKey.ToCString()); + myWriter->Int(anIter.Value()); + } + } + if (theNamedData->HasReals()) + { + const TDataStd_DataMapOfStringReal& aRealProperties = theNamedData->GetRealsContainer(); + for (TDataStd_DataMapIteratorOfDataMapOfStringReal anIter(aRealProperties); + anIter.More(); anIter.Next()) + { + TCollection_AsciiString aKey(anIter.Key()); + myWriter->Key(aKey.ToCString()); + myWriter->Double(anIter.Value()); + } + } + if (theNamedData->HasStrings()) + { + const TDataStd_DataMapOfStringString& aStringProperties = theNamedData->GetStringsContainer(); + for (TDataStd_DataMapIteratorOfDataMapOfStringString anIter(aStringProperties); + anIter.More(); anIter.Next()) + { + TCollection_AsciiString aKey(anIter.Key()); + TCollection_AsciiString aValue(anIter.Value()); + myWriter->Key(aKey.ToCString()); + myWriter->String(aValue.ToCString()); + } + } + if (theNamedData->HasBytes()) + { + const TDataStd_DataMapOfStringByte& aByteProperties = theNamedData->GetBytesContainer(); + for (TDataStd_DataMapOfStringByte::Iterator anIter(aByteProperties); + anIter.More(); anIter.Next()) + { + TCollection_AsciiString aKey(anIter.Key()); + myWriter->Key(aKey.ToCString()); + myWriter->Int(anIter.Value()); + } + } + if (theNamedData->HasArraysOfIntegers()) + { + const TDataStd_DataMapOfStringHArray1OfInteger& anArrayIntegerProperties = + theNamedData->GetArraysOfIntegersContainer(); + for (TDataStd_DataMapOfStringHArray1OfInteger::Iterator anIter(anArrayIntegerProperties); + anIter.More(); anIter.Next()) + { + TCollection_AsciiString aKey(anIter.Key()); + myWriter->Key(aKey.ToCString()); + myWriter->StartArray(); + for (TColStd_HArray1OfInteger::Iterator anSubIter(anIter.Value()->Array1()); + anSubIter.More(); anSubIter.Next()) + { + myWriter->Int(anSubIter.Value()); + } + myWriter->EndArray(); + } + } + if (theNamedData->HasArraysOfReals()) + { + const TDataStd_DataMapOfStringHArray1OfReal& anArrayRealsProperties = + theNamedData->GetArraysOfRealsContainer(); + for (TDataStd_DataMapOfStringHArray1OfReal::Iterator anIter(anArrayRealsProperties); + anIter.More(); anIter.Next()) + { + TCollection_AsciiString aKey(anIter.Key()); + myWriter->Key(aKey.ToCString()); + myWriter->StartArray(); + for (TColStd_HArray1OfReal::Iterator anSubIter(anIter.Value()->Array1()); + anSubIter.More(); anSubIter.Next()) + { + myWriter->Double(anSubIter.Value()); + } + myWriter->EndArray(); + } + } +#else + (void)theNamedData; +#endif +} + // ======================================================================= // function : writeSamplers // purpose : diff --git a/src/RWGltf/RWGltf_CafWriter.hxx b/src/RWGltf/RWGltf_CafWriter.hxx index b2cfa9ba91..fe642bd5e6 100644 --- a/src/RWGltf/RWGltf_CafWriter.hxx +++ b/src/RWGltf/RWGltf_CafWriter.hxx @@ -34,6 +34,7 @@ class RWMesh_FaceIterator; class RWGltf_GltfOStreamWriter; class RWGltf_GltfMaterialMap; class RWGltf_GltfSceneNodeMap; +class TDataStd_NamedData; class TDocStd_Document; //! glTF writer context from XCAF document. @@ -349,6 +350,10 @@ protected: //! @param theMaterialMap [out] map of materials, filled with textures Standard_EXPORT virtual void writeTextures (const RWGltf_GltfSceneNodeMap& theSceneNodeMap); + //! Write nodes.extras section with key-value attributes. + //! @param theNamedData [in] attributes map to process. + Standard_EXPORT virtual void writeExtrasAttributes(const Handle(TDataStd_NamedData)& theNamedData); + protected: //! Shape + Style pair. diff --git a/tests/metadata/gltf_export/A1 b/tests/metadata/gltf_export/A1 new file mode 100644 index 0000000000..836d0e916f --- /dev/null +++ b/tests/metadata/gltf_export/A1 @@ -0,0 +1,3 @@ +# !!!! This file is generated automatically, do not edit manually! See end script +set filename bug28345_30338.stp +set ref_size 5896 diff --git a/tests/metadata/gltf_export/A2 b/tests/metadata/gltf_export/A2 new file mode 100644 index 0000000000..734de94be3 --- /dev/null +++ b/tests/metadata/gltf_export/A2 @@ -0,0 +1,3 @@ +# !!!! This file is generated automatically, do not edit manually! See end script +set filename bug28389_CONFIDENTIAL_SHEET_METAL_F3D.stp +set ref_size 86278 diff --git a/tests/metadata/gltf_export/A3 b/tests/metadata/gltf_export/A3 new file mode 100644 index 0000000000..b1020fdb4c --- /dev/null +++ b/tests/metadata/gltf_export/A3 @@ -0,0 +1,3 @@ +# !!!! This file is generated automatically, do not edit manually! See end script +set filename bug28444_nist_ftc_06_asme1_ct5240_rd.stp +set ref_size 85383 diff --git a/tests/metadata/gltf_export/A4 b/tests/metadata/gltf_export/A4 new file mode 100644 index 0000000000..6cdc3c7549 --- /dev/null +++ b/tests/metadata/gltf_export/A4 @@ -0,0 +1,3 @@ +# !!!! This file is generated automatically, do not edit manually! See end script +set filename bug29525_rev_part_neu_01.prt_converted_from_datakit.stp +set ref_size 80996 diff --git a/tests/metadata/gltf_export/A5 b/tests/metadata/gltf_export/A5 new file mode 100644 index 0000000000..3e132d8a79 --- /dev/null +++ b/tests/metadata/gltf_export/A5 @@ -0,0 +1,3 @@ +# !!!! This file is generated automatically, do not edit manually! See end script +set filename bug29633_nist_ctc_05_asme1_ap242-1.stp +set ref_size 69902 diff --git a/tests/metadata/gltf_export/A6 b/tests/metadata/gltf_export/A6 new file mode 100644 index 0000000000..db247e76eb --- /dev/null +++ b/tests/metadata/gltf_export/A6 @@ -0,0 +1,3 @@ +# !!!! This file is generated automatically, do not edit manually! See end script +set filename bug29803.stp +set ref_size 17032 diff --git a/tests/metadata/gltf_export/A7 b/tests/metadata/gltf_export/A7 new file mode 100644 index 0000000000..3bb42faecf --- /dev/null +++ b/tests/metadata/gltf_export/A7 @@ -0,0 +1,3 @@ +# !!!! This file is generated automatically, do not edit manually! See end script +set filename sp7_04-do-242.stp +set ref_size 224779 diff --git a/tests/metadata/gltf_export/A8 b/tests/metadata/gltf_export/A8 new file mode 100644 index 0000000000..8c2edc7f18 --- /dev/null +++ b/tests/metadata/gltf_export/A8 @@ -0,0 +1,3 @@ +# !!!! This file is generated automatically, do not edit manually! See end script +set filename bug32087_part.stp +set ref_size 15789 diff --git a/tests/metadata/gltf_export/A9 b/tests/metadata/gltf_export/A9 new file mode 100644 index 0000000000..2428cb4e23 --- /dev/null +++ b/tests/metadata/gltf_export/A9 @@ -0,0 +1,3 @@ +# !!!! This file is generated automatically, do not edit manually! See end script +set filename nist_ftc_08_asme1_ap242-2.stp +set ref_size 118200 diff --git a/tests/metadata/gltf_export/begin b/tests/metadata/gltf_export/begin new file mode 100644 index 0000000000..56cb94b803 --- /dev/null +++ b/tests/metadata/gltf_export/begin @@ -0,0 +1 @@ +pload MODELING diff --git a/tests/metadata/gltf_export/end b/tests/metadata/gltf_export/end new file mode 100644 index 0000000000..8e4881b137 --- /dev/null +++ b/tests/metadata/gltf_export/end @@ -0,0 +1,39 @@ +# Set flag dump_file to 1 in order to regenerate script files with actual data +# used as reference. In this mode all tests intentionally report failure. +set dump_file 0 + +# Read original file +if { [string length $filename] > 1} { + set path_file [locate_data_file $filename] + if { [catch { ReadFile D $path_file } catch_result] } { + set err_msg "Error: file was not read - exception " + puts $err_msg + } +} + +# mesh the shape before Gltf writing +XGetOneShape a D +incmesh a 0.1 + +# write file +WriteGltf D $imagedir/${casename}_D_First.gltf +set aSize [file size $imagedir/${casename}_D_First.gltf] + +if { $dump_file == 1 } { + set fd_stream [open $dirname/$groupname/$gridname/$casename w] + puts $fd_stream "# !!!! This file is generated automatically, do not edit manually! See end script" + puts $fd_stream "set filename $filename" + puts $fd_stream "set ref_size $aSize" + close $fd_stream + puts "Error : Running in regeneration mode, comparison was not performed!" +} else { + if {$aSize != $ref_size} { + puts "Error: Wrong file size $aSize instead of $ref_size" + } +} + +# finalize scenario +Close D +file delete $imagedir/${casename}_D_First.gltf +file delete $imagedir/${casename}_D_First.bin +puts "TEST COMPLETED" diff --git a/tests/metadata/grids.list b/tests/metadata/grids.list index c7e242aaea..3dc7702c6b 100644 --- a/tests/metadata/grids.list +++ b/tests/metadata/grids.list @@ -1 +1,2 @@ 001 step +002 gltf_export diff --git a/tests/metadata/end b/tests/metadata/step/end similarity index 100% rename from tests/metadata/end rename to tests/metadata/step/end