]> OCCT Git - occt.git/commitdiff
0033426: Data Exchange, VRML - Impossible to import VRML V1 CR0-WEEK-37 IR-2023-09-15
authorichesnok <ichesnok@opencascade.com>
Mon, 24 Jul 2023 08:43:30 +0000 (09:43 +0100)
committerichesnok <ichesnok@opencascade.com>
Thu, 14 Sep 2023 07:16:45 +0000 (08:16 +0100)
VrmlData_ShapeNode creating (for vrml v1 case) was added

src/VrmlData/VrmlData_Group.cxx
src/VrmlData/VrmlData_Material.cxx
src/VrmlData/VrmlData_Material.hxx
src/VrmlData/VrmlData_Scene.cxx
tests/bugs/stlvrml/bug33426 [new file with mode: 0644]

index 3af1d8c706f6aac755ae565299a9d933380761e7..27b10e54c22f2df7d4f08470ce7491cf505cf44e 100644 (file)
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
+#include <VrmlData_Coordinate.hxx>
+#include <VrmlData_Geometry.hxx>
 #include <VrmlData_Group.hxx>
+#include <VrmlData_IndexedFaceSet.hxx>
+#include <VrmlData_IndexedLineSet.hxx>
 #include <VrmlData_Scene.hxx>
 #include <VrmlData_WorldInfo.hxx>
 #include <VrmlData_InBuffer.hxx>
 #include <VrmlData_ListOfNode.hxx>
+#include <VrmlData_ShapeNode.hxx>
 #include <VrmlData_UnknownNode.hxx>
 #include <Precision.hxx>
 #include <gp_Ax1.hxx>
@@ -206,8 +211,8 @@ VrmlData_ErrorStatus VrmlData_Group::Read (VrmlData_InBuffer& theBuffer)
       TCollection_AsciiString aDummy;
       aStatus = Scene().ReadWord (theBuffer, aDummy);
     }
-    else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "Separator") ||
-             VRMLDATA_LCOMPARE (theBuffer.LinePtr, "Switch")) {
+    else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "Switch"))
+    {
       Standard_Boolean isBracketed (Standard_False);
       // Read the opening bracket for the list of children
       if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
@@ -238,7 +243,99 @@ VrmlData_ErrorStatus VrmlData_Group::Read (VrmlData_InBuffer& theBuffer)
           break;
       }
     }
-    else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "ShapeHints")) {
+    else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "TransformSeparator") ||
+             VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Separator"))
+    {
+      Handle(VrmlData_Group) aGroupNode = new VrmlData_Group(Scene(), "");
+      Standard_Boolean isBracketed(Standard_False);
+      // Read the opening bracket for the list of children
+      if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
+        break;
+
+      if (theBuffer.LinePtr[0] == '{') {
+        theBuffer.LinePtr++;
+        if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
+          break;
+        isBracketed = Standard_True;
+      }
+
+      // Read the child nodes
+      Handle(VrmlData_Node) aChildNode;
+      while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
+        // read the end-of-list bracket
+        if (isBracketed && theBuffer.LinePtr[0] == '}') {
+          theBuffer.LinePtr++;
+          break;
+        }
+        // otherwise read a node
+        if (!OK(aStatus, ReadNode(theBuffer, aChildNode)))
+          break;
+
+        aGroupNode->AddNode(aChildNode);
+        if (isBracketed == Standard_False)
+          break;
+      }
+
+      Handle(VrmlData_Coordinate) aCoord;
+      Handle(VrmlData_IndexedFaceSet) anIndFaceSet;
+      Handle(VrmlData_IndexedLineSet) anIndLineSet;
+      Handle(VrmlData_Appearance) anAppearance;
+      for (VrmlData_ListOfNode::Iterator anIt = aGroupNode->NodeIterator(); anIt.More(); anIt.Next())
+      {
+        Handle(VrmlData_Node) aNode = anIt.Value();
+        if (aNode.IsNull())
+          continue;
+
+        if (anIt.Value()->IsKind(STANDARD_TYPE(VrmlData_Coordinate)))
+        {
+          aCoord = Handle(VrmlData_Coordinate)::DownCast(anIt.Value());
+        }
+        else if (anIt.Value()->IsKind(STANDARD_TYPE(VrmlData_IndexedFaceSet)))
+        {
+          anIndFaceSet = Handle(VrmlData_IndexedFaceSet)::DownCast(anIt.Value());
+          if (!aCoord.IsNull())
+          {
+            anIndFaceSet->SetCoordinates(aCoord);
+          }
+        }
+        else if (anIt.Value()->IsKind(STANDARD_TYPE(VrmlData_IndexedLineSet)))
+        {
+          anIndLineSet = Handle(VrmlData_IndexedLineSet)::DownCast(anIt.Value());
+          if (!aCoord.IsNull())
+          {
+            anIndLineSet->SetCoordinates(aCoord);
+          }
+        }
+        else if (anIt.Value()->IsKind(STANDARD_TYPE(VrmlData_Material)))
+        {
+          Handle(VrmlData_Material) aMaterial = Handle(VrmlData_Material)::DownCast(anIt.Value());
+          anAppearance = new VrmlData_Appearance();
+          anAppearance->SetMaterial(aMaterial);
+        }
+      }
+
+      if (!aCoord.IsNull())
+      {
+        Handle(VrmlData_ShapeNode) aShapeNode = new VrmlData_ShapeNode(Scene(), "");
+        if (!anIndFaceSet.IsNull())
+        {
+          aShapeNode->SetGeometry(anIndFaceSet);
+        }
+        else if (!anIndLineSet.IsNull())
+        {
+          aShapeNode->SetGeometry(anIndLineSet);
+        }
+        if (!anAppearance.IsNull())
+        {
+          aShapeNode->SetAppearance(anAppearance);
+        }
+        aGroupNode->AddNode(aShapeNode);
+      }
+
+      AddNode(aGroupNode);
+    }
+    else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "ShapeHints") ||
+             VRMLDATA_LCOMPARE (theBuffer.LinePtr, "DirectionalLight")) {
       // Skip this tag
       if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
         break;
@@ -305,6 +402,14 @@ VrmlData_ErrorStatus VrmlData_Group::Read (VrmlData_InBuffer& theBuffer)
         aStatus = VrmlData_VrmlFormatError;
         break;
       }
+    else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "DEF"))
+    {
+      TCollection_AsciiString aWord;
+      if (OK(aStatus, VrmlData_Scene::ReadWord(theBuffer, aWord)))
+      {
+        setName(aWord.ToCString());
+      }
+    }
     else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "url")) {
       NCollection_List<TCollection_AsciiString> lstURL;
       if (OK(aStatus, ReadMultiString (theBuffer, lstURL))) {
index 7361efc9a5c53b993661ed840a682021c0520f3b..c3644f56fd381bdecf3d9aa0a078fb8cb46cb77a 100644 (file)
@@ -26,6 +26,109 @@ IMPLEMENT_STANDARD_RTTIEXT(VrmlData_Material,VrmlData_Node)
 #pragma warning (disable:4996)
 #endif
 
+namespace
+{
+  static const Standard_Real THE_MAT_PREC = 0.001 * Precision::Confusion();
+
+  //=======================================================================
+  //function : isValidValue
+  //purpose  : 
+  //=======================================================================
+  static bool isValidValue(Standard_Real theVal)
+  {
+    return theVal >= -THE_MAT_PREC && theVal <= 1.0 + THE_MAT_PREC;
+  }
+
+  //=======================================================================
+  //function : isValidColor
+  //purpose  : 
+  //=======================================================================
+  static bool isValidColor(const gp_XYZ & theVec3)
+  {
+    return isValidValue(theVec3.X()) && isValidValue(theVec3.Y()) && isValidValue(theVec3.Z());
+  }
+
+  //=======================================================================
+  //function : parseColor
+  //purpose  : 
+  //=======================================================================
+  static bool parseColor(VrmlData_ErrorStatus & theStatus,
+                         VrmlData_InBuffer & theBuffer,
+                         gp_XYZ & theColor,
+                         const VrmlData_Scene & theScene)
+  {
+    if (!VrmlData_Node::OK(theStatus, VrmlData_Scene::ReadLine(theBuffer)))
+    {
+      return false;
+    }
+    
+    bool isArray = *theBuffer.LinePtr == '[';
+    if (isArray)
+    {
+      ++theBuffer.LinePtr;
+    }
+    theStatus = theScene.ReadXYZ(theBuffer, theColor, Standard_False, Standard_False);
+    if (isArray)
+    {
+      if (VrmlData_Node::OK(theStatus, VrmlData_Scene::ReadLine(theBuffer))
+          && *theBuffer.LinePtr == ']')
+      {
+        ++theBuffer.LinePtr;
+      }
+      else
+      {
+        theStatus = VrmlData_VrmlFormatError;
+      }
+    }
+    if (!isValidColor(theColor))
+    {
+      theStatus = VrmlData_IrrelevantNumber;
+      return false;
+    }
+    return true;
+  }
+
+  //=======================================================================
+  //function : parseScalar
+  //purpose  : 
+  //=======================================================================
+  static bool parseScalar(VrmlData_ErrorStatus & theStatus,
+                          VrmlData_InBuffer & theBuffer,
+                          Standard_Real & theValue,
+                          const VrmlData_Scene & theScene)
+  {
+    if (!VrmlData_Node::OK(theStatus, VrmlData_Scene::ReadLine(theBuffer)))
+    {
+      return false;
+    }
+    
+    bool isArray = *theBuffer.LinePtr == '[';
+    if (isArray)
+    {
+      ++theBuffer.LinePtr;
+    }
+
+    theStatus = theScene.ReadReal(theBuffer, theValue, Standard_False, Standard_False);
+    if (isArray)
+    {
+      if (VrmlData_Node::OK(theStatus, VrmlData_Scene::ReadLine(theBuffer))
+          && *theBuffer.LinePtr == ']')
+      {
+        ++theBuffer.LinePtr;
+      }
+      else
+      {
+        theStatus = VrmlData_VrmlFormatError;
+      }
+    }
+    if (!isValidValue(theValue))
+    {
+      theStatus = VrmlData_IrrelevantNumber;
+      return false;
+    }
+    return true;
+  }
+}
 
 //=======================================================================
 //function : VrmlData_Material()
@@ -36,6 +139,7 @@ VrmlData_Material::VrmlData_Material ()
   : myAmbientIntensity        (0.2),
     myShininess               (0.2),
     myTransparency            (0.),
+    myAmbientColor(0., 0., 0., Quantity_TOC_RGB),
     myDiffuseColor            (0.8, 0.8, 0.8, Quantity_TOC_sRGB),
     myEmissiveColor           (Quantity_NOC_BLACK),
     mySpecularColor           (Quantity_NOC_BLACK)
@@ -55,6 +159,7 @@ VrmlData_Material::VrmlData_Material (const VrmlData_Scene&  theScene,
     myAmbientIntensity        (theAmbientIntens < 0. ? 0.2 : theAmbientIntens),
     myShininess               (theShininess     < 0. ? 0.2 : theShininess),
     myTransparency            (theTransparency  < 0  ? 0.  : theTransparency),
+    myAmbientColor            (0., 0., 0., Quantity_TOC_RGB),
     myDiffuseColor            (0.8, 0.8, 0.8, Quantity_TOC_sRGB),
     myEmissiveColor           (Quantity_NOC_BLACK),
     mySpecularColor           (Quantity_NOC_BLACK)
@@ -79,6 +184,7 @@ Handle(VrmlData_Node) VrmlData_Material::Clone
   aResult->SetAmbientIntensity (myAmbientIntensity);
   aResult->SetShininess        (myShininess);
   aResult->SetTransparency     (myTransparency);
+  aResult->SetAmbientColor     (myAmbientColor);
   aResult->SetDiffuseColor     (myDiffuseColor);
   aResult->SetEmissiveColor    (myEmissiveColor);
   aResult->SetSpecularColor    (mySpecularColor);
@@ -93,66 +199,37 @@ Handle(VrmlData_Node) VrmlData_Material::Clone
 VrmlData_ErrorStatus VrmlData_Material::Read (VrmlData_InBuffer& theBuffer)
 {
   VrmlData_ErrorStatus aStatus;
-  const Standard_Real aConf = 0.001 * Precision::Confusion();
   Standard_Real anIntensity[3] = { 0.2, 0.2, 0. };
-  gp_XYZ        aColor[3] = {
+  gp_XYZ        aColor[4] = {
+    gp_XYZ (0.0, 0.0, 0.0),
     gp_XYZ (0.8, 0.8, 0.8),
     gp_XYZ (0.0, 0.0, 0.0),
     gp_XYZ (0.0, 0.0, 0.0)
   };
   while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
-    if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "ambientIntensity")) {
-      if (OK(aStatus, Scene().ReadReal (theBuffer, anIntensity[0],
-                                        Standard_False, Standard_False)))
-        if (anIntensity[0] < -aConf || anIntensity[0] > 1.+aConf) {
-          aStatus = VrmlData_IrrelevantNumber;
-          break;
-        }
-    } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "shininess")) {
-      if (OK(aStatus, Scene().ReadReal (theBuffer, anIntensity[1],
-                                        Standard_False, Standard_False)))
-        if (anIntensity[1] < -aConf || anIntensity[1] > 1.+aConf) {
-          aStatus = VrmlData_IrrelevantNumber;
-          break;
-        }
-    } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "transparency")) {
-      if (OK(aStatus, Scene().ReadReal (theBuffer, anIntensity[2],
-                                        Standard_False, Standard_False)))
-        if (anIntensity[2] < -aConf || anIntensity[2] > 1.+aConf) {
-          aStatus = VrmlData_IrrelevantNumber;
-          break;
-        }
-    } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "diffuseColor")) {
-      if (OK(aStatus, Scene().ReadXYZ (theBuffer, aColor[0],
-                                       Standard_False, Standard_False)))
-        if (aColor[0].X() < -aConf || aColor[0].X() > 1.+aConf ||
-            aColor[0].Y() < -aConf || aColor[0].Y() > 1.+aConf ||
-            aColor[0].Z() < -aConf || aColor[0].Z() > 1.+aConf)
-        {
-          aStatus = VrmlData_IrrelevantNumber;
-          break;
-        }
-    } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "emissiveColor")) {
-      if (OK(aStatus, Scene().ReadXYZ (theBuffer, aColor[1],
-                                       Standard_False, Standard_False)))
-        if (aColor[1].X() < -aConf || aColor[1].X() > 1.+aConf ||
-            aColor[1].Y() < -aConf || aColor[1].Y() > 1.+aConf ||
-            aColor[1].Z() < -aConf || aColor[1].Z() > 1.+aConf)
-        {
-          aStatus = VrmlData_IrrelevantNumber;
-          break;
-        }
-    } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "specularColor")) {
-      if (OK(aStatus, Scene().ReadXYZ (theBuffer, aColor[2],
-                                       Standard_False, Standard_False)))
-        if (aColor[2].X() < -aConf || aColor[2].X() > 1.+aConf ||
-            aColor[2].Y() < -aConf || aColor[2].Y() > 1.+aConf ||
-            aColor[2].Z() < -aConf || aColor[2].Z() > 1.+aConf)
-        {
-          aStatus = VrmlData_IrrelevantNumber;
-          break;
-        }
-    } else
+    if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "ambientIntensity"))
+    {
+      parseScalar(aStatus, theBuffer, anIntensity[0], Scene());
+    }
+    else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "shininess")) {
+      parseScalar(aStatus, theBuffer, anIntensity[1], Scene());
+    }
+    else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "transparency")) {
+      parseScalar(aStatus, theBuffer, anIntensity[2], Scene());
+    }
+    else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "ambientColor")) {
+      parseColor(aStatus, theBuffer, aColor[0], Scene());
+    }
+    else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "diffuseColor")) {
+      parseColor(aStatus, theBuffer, aColor[1], Scene());
+    }
+    else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "emissiveColor")) {
+      parseColor(aStatus, theBuffer, aColor[2], Scene());
+    }
+    else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "specularColor")) {
+      parseColor(aStatus, theBuffer, aColor[3], Scene());
+    }
+    else
       break;
 
     if (!OK(aStatus))
@@ -168,11 +245,13 @@ VrmlData_ErrorStatus VrmlData_Material::Read (VrmlData_InBuffer& theBuffer)
     myAmbientIntensity  = anIntensity[0];
     myShininess         = anIntensity[1];
     myTransparency      = anIntensity[2];
-    myDiffuseColor.SetValues  (aColor[0].X(), aColor[0].Y(), aColor[0].Z(),
+    myAmbientColor.SetValues  (aColor[0].X(), aColor[0].Y(), aColor[0].Z(),
+                               Quantity_TOC_sRGB);
+    myDiffuseColor.SetValues  (aColor[1].X(), aColor[1].Y(), aColor[1].Z(),
                                Quantity_TOC_sRGB);
-    myEmissiveColor.SetValues (aColor[1].X(), aColor[1].Y(), aColor[1].Z(),
+    myEmissiveColor.SetValues (aColor[2].X(), aColor[2].Y(), aColor[2].Z(),
                                Quantity_TOC_sRGB);
-    mySpecularColor.SetValues (aColor[2].X(), aColor[2].Y(), aColor[2].Z(),
+    mySpecularColor.SetValues (aColor[3].X(), aColor[3].Y(), aColor[3].Z(),
                                Quantity_TOC_sRGB);
   }
   return aStatus;
index a2002e860ca890c31bf31cdb22b58ad654baf9e8..15044a67c56bf4515cc6871537b06f6a927f78be 100644 (file)
@@ -60,6 +60,12 @@ class VrmlData_Material : public VrmlData_Node
   inline Standard_Real
                 Transparency    () const        { return myTransparency; }
 
+  /**
+  * Query the Ambient color
+  */
+  inline const Quantity_Color&
+                AmbientColor    () const        { return myAmbientColor; }
+
   /**
    * Query the Diffuse color
    */
@@ -97,6 +103,14 @@ class VrmlData_Material : public VrmlData_Node
   inline void   SetTransparency (const Standard_Real theTransparency)
   { myTransparency = theTransparency; }
 
+  /**
+  * Query the Ambient color
+  */
+  inline void   SetAmbientColor (const Quantity_Color& theColor)
+  {
+    myAmbientColor = theColor;
+  }
+
   /**
    * Query the Diffuse color
    */
@@ -150,6 +164,7 @@ class VrmlData_Material : public VrmlData_Node
   Standard_Real         myAmbientIntensity;
   Standard_Real         myShininess;
   Standard_Real         myTransparency;
+  Quantity_Color        myAmbientColor;
   Quantity_Color        myDiffuseColor;
   Quantity_Color        myEmissiveColor;
   Quantity_Color        mySpecularColor;
index 44562e34380ce1dcce9e0804dbad0f1b72eb30d6..538a35c76eb066185e0e193bd28354b2584a87f5 100644 (file)
@@ -13,7 +13,6 @@
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-#include <VrmlData_Scene.hxx>
 #include <VrmlData_Appearance.hxx>
 #include <VrmlData_Box.hxx>
 #include <VrmlData_Cone.hxx>
@@ -46,6 +45,8 @@
 #pragma warning (disable:4996)
 #endif
 
+#define VRMLDATA_LCOMPARE_SKIP(aa, bb) (strncmp (aa, bb, sizeof(bb)-1) == 0)
+
 static void     dumpNode        (Standard_OStream&              theStream,
                                  const Handle(VrmlData_Node)&   theNode,
                                  const TCollection_AsciiString& theIndent);
@@ -508,7 +509,8 @@ VrmlData_ErrorStatus VrmlData_Scene::createNode
     // create the new node
     if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Appearance"))
       aNode = new VrmlData_Appearance     (* this, strName);
-    else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Shape"))
+    else if (!VRMLDATA_LCOMPARE_SKIP(theBuffer.LinePtr, "ShapeHints")
+             && VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Shape"))
       aNode = new VrmlData_ShapeNode      (* this, strName);
     else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Box"))
       aNode = new VrmlData_Box            (* this, strName);
diff --git a/tests/bugs/stlvrml/bug33426 b/tests/bugs/stlvrml/bug33426
new file mode 100644 (file)
index 0000000..14fcd2c
--- /dev/null
@@ -0,0 +1,7 @@
+puts "========"
+puts "0033426: Data Exchange, VRML - Impossible to import VRML V1"
+puts "========"
+puts ""
+
+loadvrml sh [locate_data_file bug33426.vrml]
+checknbshapes sh -vertex 0 -edge 6 -wire 6 -face 1 -shell 0 -solid 0 -compsolid 0 -compound 5 -shape 18