]> OCCT Git - occt.git/commitdiff
Data Exchange, Gltf Export - Metadata support #79
authorika <ika@opencascade.com>
Mon, 30 Sep 2024 11:12:05 +0000 (12:12 +0100)
committerdpasukhi <dpasukhi@opencascade.com>
Mon, 30 Sep 2024 16:04:12 +0000 (16:04 +0000)
Add supporting of metadata key-value export into extras section of each node.

16 files changed:
src/RWGltf/RWGltf_CafWriter.cxx
src/RWGltf/RWGltf_CafWriter.hxx
tests/metadata/end [deleted file]
tests/metadata/gltf_export/A1 [new file with mode: 0644]
tests/metadata/gltf_export/A2 [new file with mode: 0644]
tests/metadata/gltf_export/A3 [new file with mode: 0644]
tests/metadata/gltf_export/A4 [new file with mode: 0644]
tests/metadata/gltf_export/A5 [new file with mode: 0644]
tests/metadata/gltf_export/A6 [new file with mode: 0644]
tests/metadata/gltf_export/A7 [new file with mode: 0644]
tests/metadata/gltf_export/A8 [new file with mode: 0644]
tests/metadata/gltf_export/A9 [new file with mode: 0644]
tests/metadata/gltf_export/begin [new file with mode: 0644]
tests/metadata/gltf_export/end [new file with mode: 0644]
tests/metadata/grids.list
tests/metadata/step/end [new file with mode: 0644]

index aa86708d3906bc8a4697ccb82485f6268f0168e3..e7ef51e9576f0b87600e0b647211060ce8edd0f4 100644 (file)
@@ -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  :
index b2cfa9ba91bb90b1b2109205024eebd8a3da73d4..fe642bd5e63a6a5661146efe7ccfbb543cac64a5 100644 (file)
@@ -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/end b/tests/metadata/end
deleted file mode 100644 (file)
index fc54e89..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-# 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
-########################################################################
-set mist 0;
-set todo_msg ""
-set todo_mask "puts \"TODO CR00000 ALL: "
-set end_line "\" \n"
-##################################################################
-
-# 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
-    append todo_msg $todo_mask $err_msg $end_line
-    set mist 1
-  }
-} else {
-  set mist 1
-}
-
-# Get information about translation
-if { $mist < 1} {
-  puts ""
-  set prop [ XGetProperties D ] 
-
-  if { [llength $prop] < 0 } {
-      puts " Metadata was NOT provided"
-    }
-}
-if { $mist < 1} {
-  # Close the document
-  if { [catch { Close D } catch_result] } {
-    set err_msg "Error : cannot close a document D - exception"
-    puts $err_msg
-    append todo_msg $todo_mask $err_msg $end_line
-  }
-}
-
-if { $mist != 1 } {
-  puts "" 
-  set result ""
-  append result [format $prop]
-}
-
-set ref_Compare 0
-# Put reference data to the test script file if option "dump" is set
-if { $dump_file == 1 } {
-  set fd_stream  [open $dirname/$groupname/$gridname/$casename w]
-  fconfigure $fd_stream -encoding utf-8
-  puts $fd_stream "# !!!! This file is generated automatically, do not edit manually! See end script"
-  puts $fd_stream "set filename $filename"
-  if { $mist != 1 } {
-    puts $fd_stream "" 
-    puts $fd_stream "set ref_data \{"
-    puts $fd_stream $result
-    puts $fd_stream "\}"
-  }
-  close $fd_stream 
-} elseif { $mist != 1 } {
-  puts "========================== Comparison with reference data ========"
-  
-  # Comparison of reference data with obtained result
-  set ref_list [split $ref_data \n]
-  set cur_list [split $result \n]
-  set nb_ref [llength $ref_list]
-  for { set i 0 } { $i < $nb_ref } { incr i } {
-    set j [expr $i + 1]
-    set refstr [lindex $ref_list $j]
-    set curstr [lindex $cur_list $i]
-    set isOK 1;
-
-    if {[string equal $refstr $curstr] == 0} {
-      incr ref_Compare
-      puts "Reference data - $refstr\n"
-      puts "Current data - $curstr\n"
-      puts "----------------------------------------------\n"
-    }
-  }
-}
-
-if { $dump_file != 0 } {
-    puts "Error : Running in regeneration mode, comparison was not performed!"
-    if { $mist != 1 } {
-      puts "Generation of test file $groupname/$gridname/$casename successful"
-    } else {
-      puts "Generation of reference data failed"
-    }
-} else {
-    if { $ref_Compare >= 1} {
-      puts "Error : differences with reference data found : $ref_Compare"
-    } else {
-      puts "Comparison of current result with reference data - OK\n"
-    }
-}
-puts "TEST COMPLETED"
diff --git a/tests/metadata/gltf_export/A1 b/tests/metadata/gltf_export/A1
new file mode 100644 (file)
index 0000000..836d0e9
--- /dev/null
@@ -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 (file)
index 0000000..734de94
--- /dev/null
@@ -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 (file)
index 0000000..b1020fd
--- /dev/null
@@ -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 (file)
index 0000000..6cdc3c7
--- /dev/null
@@ -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 (file)
index 0000000..3e132d8
--- /dev/null
@@ -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 (file)
index 0000000..db247e7
--- /dev/null
@@ -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 (file)
index 0000000..3bb42fa
--- /dev/null
@@ -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 (file)
index 0000000..8c2edc7
--- /dev/null
@@ -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 (file)
index 0000000..2428cb4
--- /dev/null
@@ -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 (file)
index 0000000..56cb94b
--- /dev/null
@@ -0,0 +1 @@
+pload MODELING
diff --git a/tests/metadata/gltf_export/end b/tests/metadata/gltf_export/end
new file mode 100644 (file)
index 0000000..8e4881b
--- /dev/null
@@ -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"
index c7e242aaeaee697a238e6099ef9b08a7cfe1cb5b..3dc7702c6b8b3a107cbc634781779178f00cf6b6 100644 (file)
@@ -1 +1,2 @@
 001 step
+002 gltf_export
diff --git a/tests/metadata/step/end b/tests/metadata/step/end
new file mode 100644 (file)
index 0000000..fc54e89
--- /dev/null
@@ -0,0 +1,98 @@
+# 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
+########################################################################
+set mist 0;
+set todo_msg ""
+set todo_mask "puts \"TODO CR00000 ALL: "
+set end_line "\" \n"
+##################################################################
+
+# 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
+    append todo_msg $todo_mask $err_msg $end_line
+    set mist 1
+  }
+} else {
+  set mist 1
+}
+
+# Get information about translation
+if { $mist < 1} {
+  puts ""
+  set prop [ XGetProperties D ] 
+
+  if { [llength $prop] < 0 } {
+      puts " Metadata was NOT provided"
+    }
+}
+if { $mist < 1} {
+  # Close the document
+  if { [catch { Close D } catch_result] } {
+    set err_msg "Error : cannot close a document D - exception"
+    puts $err_msg
+    append todo_msg $todo_mask $err_msg $end_line
+  }
+}
+
+if { $mist != 1 } {
+  puts "" 
+  set result ""
+  append result [format $prop]
+}
+
+set ref_Compare 0
+# Put reference data to the test script file if option "dump" is set
+if { $dump_file == 1 } {
+  set fd_stream  [open $dirname/$groupname/$gridname/$casename w]
+  fconfigure $fd_stream -encoding utf-8
+  puts $fd_stream "# !!!! This file is generated automatically, do not edit manually! See end script"
+  puts $fd_stream "set filename $filename"
+  if { $mist != 1 } {
+    puts $fd_stream "" 
+    puts $fd_stream "set ref_data \{"
+    puts $fd_stream $result
+    puts $fd_stream "\}"
+  }
+  close $fd_stream 
+} elseif { $mist != 1 } {
+  puts "========================== Comparison with reference data ========"
+  
+  # Comparison of reference data with obtained result
+  set ref_list [split $ref_data \n]
+  set cur_list [split $result \n]
+  set nb_ref [llength $ref_list]
+  for { set i 0 } { $i < $nb_ref } { incr i } {
+    set j [expr $i + 1]
+    set refstr [lindex $ref_list $j]
+    set curstr [lindex $cur_list $i]
+    set isOK 1;
+
+    if {[string equal $refstr $curstr] == 0} {
+      incr ref_Compare
+      puts "Reference data - $refstr\n"
+      puts "Current data - $curstr\n"
+      puts "----------------------------------------------\n"
+    }
+  }
+}
+
+if { $dump_file != 0 } {
+    puts "Error : Running in regeneration mode, comparison was not performed!"
+    if { $mist != 1 } {
+      puts "Generation of test file $groupname/$gridname/$casename successful"
+    } else {
+      puts "Generation of reference data failed"
+    }
+} else {
+    if { $ref_Compare >= 1} {
+      puts "Error : differences with reference data found : $ref_Compare"
+    } else {
+      puts "Comparison of current result with reference data - OK\n"
+    }
+}
+puts "TEST COMPLETED"