0028107: Visualization - provide a flexible interface to set custom hatch styles
authorvpa <vpa@opencascade.com>
Tue, 15 Nov 2016 18:05:52 +0000 (21:05 +0300)
committerapn <apn@opencascade.com>
Thu, 15 Dec 2016 13:28:58 +0000 (16:28 +0300)
- class Graphic3d_HatchStyle is added to provide a possibility to set up custom and predefined hatching;
- added the ability to set custom hatch patterns through bitmaps;
- test case for issue #28107

16 files changed:
src/Aspect/Aspect_HatchStyle.hxx
src/Graphic3d/FILES
src/Graphic3d/Graphic3d_AspectFillArea3d.cxx
src/Graphic3d/Graphic3d_AspectFillArea3d.hxx
src/Graphic3d/Graphic3d_ClipPlane.cxx
src/Graphic3d/Graphic3d_ClipPlane.hxx
src/Graphic3d/Graphic3d_HatchStyle.cxx [new file with mode: 0644]
src/Graphic3d/Graphic3d_HatchStyle.hxx [new file with mode: 0644]
src/OpenGl/OpenGl_AspectFace.cxx
src/OpenGl/OpenGl_Context.cxx
src/OpenGl/OpenGl_Context.hxx
src/OpenGl/OpenGl_LineAttributes.cxx
src/OpenGl/OpenGl_LineAttributes.hxx
src/V3d/V3d_Plane.cxx
src/ViewerTest/ViewerTest.cxx
tests/bugs/vis/bug28107 [new file with mode: 0644]

index 49128ce..6558a97 100644 (file)
@@ -32,6 +32,7 @@ enum Aspect_HatchStyle
   Aspect_HS_GRID_WIDE          = 4,  // TEL_HS_GRID_SPARSE
   Aspect_HS_GRID_DIAGONAL      = 1,  // TEL_HS_CROSS
   Aspect_HS_GRID_DIAGONAL_WIDE = 2,  // TEL_HS_CROSS_SPARSE
+  Aspect_HS_NB                 = 13,
 };
 
 #endif // _Aspect_HatchStyle_HeaderFile
index 7bb0d53..c42a5eb 100755 (executable)
@@ -59,6 +59,8 @@ Graphic3d_Group.cxx
 Graphic3d_Group.hxx
 Graphic3d_GroupAspect.hxx
 Graphic3d_GroupDefinitionError.hxx
+Graphic3d_HatchStyle.hxx
+Graphic3d_HatchStyle.cxx
 Graphic3d_HighlightStyle.hxx
 Graphic3d_HighlightStyle.cxx
 Graphic3d_HorizontalTextAlignment.hxx
index 1591213..a8273d9 100644 (file)
@@ -28,7 +28,7 @@ Graphic3d_AspectFillArea3d::Graphic3d_AspectFillArea3d()
   myInteriorStyle       (Aspect_IS_EMPTY),
   myEdgeType            (Aspect_TOL_SOLID),
   myEdgeWidth           (1.0f),
-  myHatchStyle          (Aspect_HS_VERTICAL),
+  myHatchStyle          (Handle(Graphic3d_HatchStyle)()),
   myToDistinguishMaterials (false),
   myToDrawEdges         (false),
   myToSuppressBackFaces (true),
@@ -56,7 +56,7 @@ Graphic3d_AspectFillArea3d::Graphic3d_AspectFillArea3d (const Aspect_InteriorSty
   myInteriorStyle       (theInteriorStyle),
   myEdgeType            (theEdgeLineType),
   myEdgeWidth           ((float )theEdgeLineWidth),
-  myHatchStyle          (Aspect_HS_VERTICAL),
+  myHatchStyle          (Handle(Graphic3d_HatchStyle)()),
   myToDistinguishMaterials (false),
   myToDrawEdges         (false),
   myToSuppressBackFaces (true),
index 6c75858..e4d0f28 100644 (file)
@@ -21,7 +21,7 @@
 #include <Aspect_PolygonOffsetMode.hxx>
 #include <Aspect_InteriorStyle.hxx>
 #include <Aspect_TypeOfLine.hxx>
-#include <Aspect_HatchStyle.hxx>
+#include <Graphic3d_HatchStyle.hxx>
 #include <Graphic3d_MaterialAspect.hxx>
 #include <Graphic3d_PolygonOffset.hxx>
 #include <Graphic3d_ShaderProgram.hxx>
@@ -247,10 +247,23 @@ public:
 public:
 
   //! Returns the hatch type used when InteriorStyle is IS_HATCH
-  Aspect_HatchStyle HatchStyle() const { return myHatchStyle; }
+  const Handle(Graphic3d_HatchStyle)& HatchStyle() const { return myHatchStyle; }
 
   //! Modifies the hatch type used when InteriorStyle is IS_HATCH
-  void SetHatchStyle (const Aspect_HatchStyle theStyle) { myHatchStyle = theStyle; }
+  void SetHatchStyle (const Handle(Graphic3d_HatchStyle)& theStyle) { myHatchStyle = theStyle; }
+
+  //! Modifies the hatch type used when InteriorStyle is IS_HATCH
+  //! @warning This method always creates a new handle for a given hatch style
+  void SetHatchStyle (const Aspect_HatchStyle theStyle)
+  {
+    if (theStyle == Aspect_HS_SOLID)
+    {
+      myHatchStyle.Nullify();
+      return;
+    }
+
+    myHatchStyle = new Graphic3d_HatchStyle (theStyle);
+  }
 
   //! Returns the current values.
   Standard_DEPRECATED("Deprecated method Values() should be replaced by individual property getters")
@@ -291,13 +304,13 @@ protected:
   Graphic3d_MaterialAspect        myFrontMaterial;
   Graphic3d_MaterialAspect        myBackMaterial;
 
-  Quantity_ColorRGBA      myInteriorColor;
-  Quantity_ColorRGBA      myBackInteriorColor;
-  Quantity_ColorRGBA      myEdgeColor;
-  Aspect_InteriorStyle    myInteriorStyle;
-  Aspect_TypeOfLine       myEdgeType;
-  Standard_ShortReal      myEdgeWidth;
-  Aspect_HatchStyle       myHatchStyle;
+  Quantity_ColorRGBA           myInteriorColor;
+  Quantity_ColorRGBA           myBackInteriorColor;
+  Quantity_ColorRGBA           myEdgeColor;
+  Aspect_InteriorStyle         myInteriorStyle;
+  Aspect_TypeOfLine            myEdgeType;
+  Standard_ShortReal           myEdgeWidth;
+  Handle(Graphic3d_HatchStyle) myHatchStyle;
 
   Graphic3d_PolygonOffset myPolygonOffset;
   bool                    myToDistinguishMaterials;
index abc1821..6c6d7e7 100755 (executable)
@@ -201,6 +201,16 @@ void Graphic3d_ClipPlane::SetCappingHatch (const Aspect_HatchStyle theStyle)
 }
 
 // =======================================================================
+// function : SetCappingCustomHatch
+// purpose  :
+// =======================================================================
+void Graphic3d_ClipPlane::SetCappingCustomHatch (const Handle(Graphic3d_HatchStyle)& theStyle)
+{
+  myAspect->SetHatchStyle (theStyle);
+  ++myAspectMod;
+}
+
+// =======================================================================
 // function : SetCappingHatchOn
 // purpose  :
 // =======================================================================
index 4664f85..08f33ae 100755 (executable)
@@ -144,7 +144,14 @@ public: // @name user-defined graphical attributes
   Standard_EXPORT void SetCappingHatch (const Aspect_HatchStyle theStyle);
 
   //! @return hatching style.
-  Aspect_HatchStyle CappingHatch() const { return myAspect->HatchStyle(); }
+  Aspect_HatchStyle CappingHatch() const { return (Aspect_HatchStyle)myAspect->HatchStyle()->HatchType(); }
+
+  //! Set custom hatch style (stipple) and turn hatching on.
+  //! @param theStyle [in] the hatch pattern.
+  Standard_EXPORT void SetCappingCustomHatch (const Handle(Graphic3d_HatchStyle)& theStyle);
+
+  //! @return hatching style.
+  const Handle(Graphic3d_HatchStyle)& CappingCustomHatch() const { return myAspect->HatchStyle(); }
 
   //! Turn on hatching.
   Standard_EXPORT void SetCappingHatchOn();
diff --git a/src/Graphic3d/Graphic3d_HatchStyle.cxx b/src/Graphic3d/Graphic3d_HatchStyle.cxx
new file mode 100644 (file)
index 0000000..136119d
--- /dev/null
@@ -0,0 +1,518 @@
+// Created on: 2016-11-14
+// Created by: Varvara POSKONINA
+// Copyright (c) 2016 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <Graphic3d_HatchStyle.hxx>
+#include <NCollection_AlignedAllocator.hxx>
+#include <Standard_Atomic.hxx>
+#include <Standard_ProgramError.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT (Graphic3d_HatchStyle, Standard_Transient)
+
+static const unsigned int myPredefinedPatterns[Aspect_HS_NB][32] =
+{
+  // Aspect_HS_SOLID
+  {
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF,
+    0xFFFFFFFF
+  },
+  // Aspect_HS_GRID_DIAGONAL
+  {
+    0xFFFFFFFF,
+    0xBBBBBBBB,
+    0xEEEEEEEE,
+    0xBBBBBBBB,
+    0xEEEEEEEE,
+    0xBBBBBBBB,
+    0xEEEEEEEE,
+    0xBBBBBBBB,
+    0xEEEEEEEE,
+    0xBBBBBBBB,
+    0xEEEEEEEE,
+    0xBBBBBBBB,
+    0xEEEEEEEE,
+    0xBBBBBBBB,
+    0xEEEEEEEE,
+    0xBBBBBBBB,
+    0xEEEEEEEE,
+    0xBBBBBBBB,
+    0xEEEEEEEE,
+    0xBBBBBBBB,
+    0xEEEEEEEE,
+    0xBBBBBBBB,
+    0xEEEEEEEE,
+    0xBBBBBBBB,
+    0xEEEEEEEE,
+    0xBBBBBBBB,
+    0xEEEEEEEE,
+    0xBBBBBBBB,
+    0xEEEEEEEE,
+    0xBBBBBBBB,
+    0xEEEEEEEE,
+    0xBBBBBBBB
+  },
+  // Aspect_HS_GRID_DIAGONAL_WIDE
+  {
+    0x81818181,
+    0x24242424,
+    0x18181818,
+    0x42424242,
+    0x81818181,
+    0x24242424,
+    0x18181818,
+    0x42424242,
+    0x81818181,
+    0x24242424,
+    0x18181818,
+    0x42424242,
+    0x81818181,
+    0x24242424,
+    0x18181818,
+    0x42424242,
+    0x81818181,
+    0x24242424,
+    0x18181818,
+    0x42424242,
+    0x81818181,
+    0x24242424,
+    0x18181818,
+    0x42424242,
+    0x81818181,
+    0x24242424,
+    0x18181818,
+    0x42424242,
+    0x81818181,
+    0x24242424,
+    0x18181818,
+    0x42424242
+  },
+  // Aspect_HS_GRID
+  {
+    0xFFFFFFFF,
+    0x88888888,
+    0xFFFFFFFF,
+    0x88888888,
+    0xFFFFFFFF,
+    0x88888888,
+    0xFFFFFFFF,
+    0x88888888,
+    0xFFFFFFFF,
+    0x88888888,
+    0xFFFFFFFF,
+    0x88888888,
+    0xFFFFFFFF,
+    0x88888888,
+    0xFFFFFFFF,
+    0x88888888,
+    0xFFFFFFFF,
+    0x88888888,
+    0xFFFFFFFF,
+    0x88888888,
+    0xFFFFFFFF,
+    0x88888888,
+    0xFFFFFFFF,
+    0x88888888,
+    0xFFFFFFFF,
+    0x88888888,
+    0xFFFFFFFF,
+    0x88888888,
+    0xFFFFFFFF,
+    0x88888888,
+    0xFFFFFFFF,
+    0x88888888
+  },
+  // Aspect_HS_GRID_WIDE
+  {
+    0xFFFFFFFF,
+    0x80808080,
+    0x80808080,
+    0x80808080,
+    0xFFFFFFFF,
+    0x80808080,
+    0x80808080,
+    0x80808080,
+    0xFFFFFFFF,
+    0x80808080,
+    0x80808080,
+    0x80808080,
+    0xFFFFFFFF,
+    0x80808080,
+    0x80808080,
+    0x80808080,
+    0xFFFFFFFF,
+    0x80808080,
+    0x80808080,
+    0x80808080,
+    0xFFFFFFFF,
+    0x80808080,
+    0x80808080,
+    0x80808080,
+    0xFFFFFFFF,
+    0x80808080,
+    0x80808080,
+    0x80808080,
+    0xFFFFFFFF,
+    0x80808080,
+    0x80808080,
+    0x80808080
+  },
+  // Aspect_HS_DIAGONAL_45
+  {
+    0x88888888,
+    0x22222222,
+    0x88888888,
+    0x22222222,
+    0x88888888,
+    0x22222222,
+    0x88888888,
+    0x22222222,
+    0x88888888,
+    0x22222222,
+    0x88888888,
+    0x22222222,
+    0x88888888,
+    0x22222222,
+    0x88888888,
+    0x22222222,
+    0x88888888,
+    0x22222222,
+    0x88888888,
+    0x22222222,
+    0x88888888,
+    0x22222222,
+    0x88888888,
+    0x22222222,
+    0x88888888,
+    0x22222222,
+    0x88888888,
+    0x22222222,
+    0x88888888,
+    0x22222222,
+    0x88888888,
+    0x22222222
+  },
+  // Aspect_HS_DIAGONAL_135
+  {
+    0x11111111,
+    0x44444444,
+    0x11111111,
+    0x44444444,
+    0x11111111,
+    0x44444444,
+    0x11111111,
+    0x44444444,
+    0x11111111,
+    0x44444444,
+    0x11111111,
+    0x44444444,
+    0x11111111,
+    0x44444444,
+    0x11111111,
+    0x44444444,
+    0x11111111,
+    0x44444444,
+    0x11111111,
+    0x44444444,
+    0x11111111,
+    0x44444444,
+    0x11111111,
+    0x44444444,
+    0x11111111,
+    0x44444444,
+    0x11111111,
+    0x44444444,
+    0x11111111,
+    0x44444444,
+    0x11111111,
+    0x44444444
+  },
+  // Aspect_HS_HORIZONTAL
+  {
+    0xFFFFFFFF,
+    0x00000000,
+    0xFFFFFFFF,
+    0x00000000,
+    0xFFFFFFFF,
+    0x00000000,
+    0xFFFFFFFF,
+    0x00000000,
+    0xFFFFFFFF,
+    0x00000000,
+    0xFFFFFFFF,
+    0x00000000,
+    0xFFFFFFFF,
+    0x00000000,
+    0xFFFFFFFF,
+    0x00000000,
+    0xFFFFFFFF,
+    0x00000000,
+    0xFFFFFFFF,
+    0x00000000,
+    0xFFFFFFFF,
+    0x00000000,
+    0xFFFFFFFF,
+    0x00000000,
+    0xFFFFFFFF,
+    0x00000000,
+    0xFFFFFFFF,
+    0x00000000,
+    0xFFFFFFFF,
+    0x00000000,
+    0xFFFFFFFF,
+    0x00000000
+  },
+  // Aspect_HS_VERTICAL
+  {
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111,
+    0x11111111
+  },
+  // Aspect_HS_DIAGONAL_45_WIDE
+  {
+    0x80808080,
+    0x20202020,
+    0x08080808,
+    0x02020202,
+    0x80808080,
+    0x20202020,
+    0x08080808,
+    0x02020202,
+    0x80808080,
+    0x20202020,
+    0x08080808,
+    0x02020202,
+    0x80808080,
+    0x20202020,
+    0x08080808,
+    0x02020202,
+    0x80808080,
+    0x20202020,
+    0x08080808,
+    0x02020202,
+    0x80808080,
+    0x20202020,
+    0x08080808,
+    0x02020202,
+    0x80808080,
+    0x20202020,
+    0x08080808,
+    0x02020202,
+    0x80808080,
+    0x20202020,
+    0x08080808,
+    0x02020202
+  },
+  // Aspect_HS_DIAGONAL_135_WIDE
+  {
+    0x01010101,
+    0x04040404,
+    0x10101010,
+    0x40404040,
+    0x01010101,
+    0x04040404,
+    0x10101010,
+    0x40404040,
+    0x01010101,
+    0x04040404,
+    0x10101010,
+    0x40404040,
+    0x01010101,
+    0x04040404,
+    0x10101010,
+    0x40404040,
+    0x01010101,
+    0x04040404,
+    0x10101010,
+    0x40404040,
+    0x01010101,
+    0x04040404,
+    0x10101010,
+    0x40404040,
+    0x01010101,
+    0x04040404,
+    0x10101010,
+    0x40404040,
+    0x01010101,
+    0x04040404,
+    0x10101010,
+    0x40404040
+  },
+  // Aspect_HS_HORIZONTAL_WIDE
+  {
+    0xFFFFFFFF,
+    0x00000000,
+    0x00000000,
+    0x00000000,
+    0xFFFFFFFF,
+    0x00000000,
+    0x00000000,
+    0x00000000,
+    0xFFFFFFFF,
+    0x00000000,
+    0x00000000,
+    0x00000000,
+    0xFFFFFFFF,
+    0x00000000,
+    0x00000000,
+    0x00000000,
+    0xFFFFFFFF,
+    0x00000000,
+    0x00000000,
+    0x00000000,
+    0xFFFFFFFF,
+    0x00000000,
+    0x00000000,
+    0x00000000,
+    0xFFFFFFFF,
+    0x00000000,
+    0x00000000,
+    0x00000000,
+    0xFFFFFFFF,
+    0x00000000,
+    0x00000000,
+    0x00000000
+  },
+  // Aspect_HS_VERTICAL_WIDE
+  {
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010,
+    0x10101010
+  }
+};
+
+namespace
+{
+  static volatile Standard_Integer THE_HATCH_STYLE_COUNTER = Aspect_HS_NB - 1;
+}
+
+//=======================================================================
+//function : Graphic3d_HatchStyle
+//purpose  :
+//=======================================================================
+Graphic3d_HatchStyle::Graphic3d_HatchStyle (const Handle(Image_PixMap)& thePattern)
+{
+  Standard_ProgramError_Raise_if (thePattern.IsNull(), "Null pointer to a hatch pattern image");
+  Standard_ProgramError_Raise_if (
+    thePattern->SizeX() != 32 || thePattern->SizeY() != 32 || thePattern->Format() != Image_PixMap::ImgGray,
+    "Hatch pattern must be a 32*32 bitmap (Image_PixMap::ImgGray format)");
+
+  const Standard_Size aByteSize = thePattern->SizeBytes();
+  Handle(NCollection_AlignedAllocator) anAllocator = new NCollection_AlignedAllocator (16);
+  myPattern = new NCollection_Buffer (anAllocator);
+  myPattern->Allocate (aByteSize);
+  std::memcpy (myPattern->ChangeData(), thePattern->Data(), aByteSize);
+
+  myHatchType = Standard_Atomic_Increment (&THE_HATCH_STYLE_COUNTER);
+}
+
+//=======================================================================
+//function : Pattern
+//purpose  :
+//=======================================================================
+const Standard_Byte* Graphic3d_HatchStyle::Pattern() const
+{
+  return !myPattern.IsNull()
+    ? myPattern->Data()
+    : (myHatchType < Aspect_HS_NB
+      ? (const Standard_Byte*)myPredefinedPatterns[myHatchType]
+      : NULL);
+}
diff --git a/src/Graphic3d/Graphic3d_HatchStyle.hxx b/src/Graphic3d/Graphic3d_HatchStyle.hxx
new file mode 100644 (file)
index 0000000..c29a3ab
--- /dev/null
@@ -0,0 +1,60 @@
+// Created on: 2016-11-14
+// Created by: Varvara POSKONINA
+// Copyright (c) 2016 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _Graphic3d_HatchStyle_HeaderFile
+#define _Graphic3d_HatchStyle_HeaderFile
+
+#include <Aspect_HatchStyle.hxx>
+#include <Image_PixMap.hxx>
+#include <NCollection_Buffer.hxx>
+
+//! A class that provides an API to use standard OCCT hatch styles
+//! defined in Aspect_HatchStyle enum or to create custom styles
+//! from a user-defined bitmap
+class Graphic3d_HatchStyle : public Standard_Transient
+{
+  DEFINE_STANDARD_RTTIEXT (Graphic3d_HatchStyle, Standard_Transient) // Type definition
+
+public:
+
+  //! Creates a new custom hatch style with the given pattern and unique style id
+  //! @warning Raises a program error if given pattern image is not a valid 32*32 bitmap
+  Standard_EXPORT Graphic3d_HatchStyle (const Handle(Image_PixMap)& thePattern);
+
+  //! Creates a new predefined hatch style with the given id in Aspect_HatchStyle enum.
+  //! GPU memory for the pattern will not be allocated.
+  Graphic3d_HatchStyle (const Aspect_HatchStyle theType)
+  : myHatchType (theType) {}
+
+  //! Returns the pattern of custom hatch style
+  Standard_EXPORT const Standard_Byte* Pattern() const;
+
+  //! In case if predefined OCCT style is used, returns
+  //! index in Aspect_HatchStyle enumeration. If the style
+  //! is custom, returns unique index of the style
+  Standard_Integer HatchType() const
+  {
+    return myHatchType;
+  }
+
+private:
+
+  Handle(NCollection_Buffer) myPattern;   //!< Image bitmap with custom hatch pattern
+  Standard_Integer           myHatchType; //!< Index of used style
+};
+
+DEFINE_STANDARD_HANDLE (Graphic3d_HatchStyle, Standard_Transient)
+
+#endif // _Graphic3d_HatchStyle_HeaderFile
index 9839412..a085a4f 100644 (file)
@@ -65,7 +65,7 @@ OpenGl_AspectFace::OpenGl_AspectFace()
                                             THE_DEFAULT_MATERIAL, THE_DEFAULT_MATERIAL)),
   myIsNoLighting (false)
 {
-  myAspect->SetHatchStyle (Aspect_HS_SOLID);
+  myAspect->SetHatchStyle (Handle(Graphic3d_HatchStyle)());
 }
 
 // =======================================================================
index dc9d63a..6b281d6 100644 (file)
@@ -3176,7 +3176,7 @@ bool OpenGl_Context::SetPolygonHatchEnabled (const bool theIsEnabled)
 // function : SetPolygonHatchStyle
 // purpose  :
 // =======================================================================
-Standard_Integer OpenGl_Context::SetPolygonHatchStyle (const Standard_Integer theType)
+Standard_Integer OpenGl_Context::SetPolygonHatchStyle (const Handle(Graphic3d_HatchStyle)& theStyle)
 {
   if (myHatchStyles.IsNull())
   {
@@ -3185,15 +3185,14 @@ Standard_Integer OpenGl_Context::SetPolygonHatchStyle (const Standard_Integer th
       // share and register for release once the resource is no longer used
       myHatchStyles = new OpenGl_LineAttributes();
       ShareResource ("OpenGl_LineAttributes", myHatchStyles);
-      myHatchStyles->Init (this);
     }
   }
-  if (myHatchStyles->TypeOfHatch() == theType)
+  if (myHatchStyles->TypeOfHatch() == theStyle->HatchType())
   {
-    return theType;
+    return theStyle->HatchType();
   }
 
-  return myHatchStyles->SetTypeOfHatch (this, theType);
+  return myHatchStyles->SetTypeOfHatch (this, theStyle);
 }
 
 // =======================================================================
index 3374d15..ac5e23b 100644 (file)
@@ -512,7 +512,7 @@ public:
   //! OpenGl_LineAttributes (Aspect_HatchStyle) or the type supported by custom
   //! implementation derived from OpenGl_LineAttributes class.
   //! @return old type of hatch.
-  Standard_EXPORT Standard_Integer SetPolygonHatchStyle (const Standard_Integer theStyle);
+  Standard_EXPORT Standard_Integer SetPolygonHatchStyle (const Handle(Graphic3d_HatchStyle)& theStyle);
 
   //! Applies matrix stored in ModelWorldState to OpenGl.
   Standard_EXPORT void ApplyModelWorldMatrix();
index 1d58616..42a13d9 100644 (file)
 
 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_LineAttributes,OpenGl_Resource)
 
-static const unsigned int myInteriors[TEL_HS_USER_DEF_START][32] =
-{
-  // Aspect_HS_SOLID
-  {
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF,
-    0xFFFFFFFF
-  },
-  // Aspect_HS_GRID_DIAGONAL
-  {
-    0xFFFFFFFF,
-    0xBBBBBBBB,
-    0xEEEEEEEE,
-    0xBBBBBBBB,
-    0xEEEEEEEE,
-    0xBBBBBBBB,
-    0xEEEEEEEE,
-    0xBBBBBBBB,
-    0xEEEEEEEE,
-    0xBBBBBBBB,
-    0xEEEEEEEE,
-    0xBBBBBBBB,
-    0xEEEEEEEE,
-    0xBBBBBBBB,
-    0xEEEEEEEE,
-    0xBBBBBBBB,
-    0xEEEEEEEE,
-    0xBBBBBBBB,
-    0xEEEEEEEE,
-    0xBBBBBBBB,
-    0xEEEEEEEE,
-    0xBBBBBBBB,
-    0xEEEEEEEE,
-    0xBBBBBBBB,
-    0xEEEEEEEE,
-    0xBBBBBBBB,
-    0xEEEEEEEE,
-    0xBBBBBBBB,
-    0xEEEEEEEE,
-    0xBBBBBBBB,
-    0xEEEEEEEE,
-    0xBBBBBBBB
-  },
-  // Aspect_HS_GRID_DIAGONAL_WIDE
-  {
-    0x81818181,
-    0x24242424,
-    0x18181818,
-    0x42424242,
-    0x81818181,
-    0x24242424,
-    0x18181818,
-    0x42424242,
-    0x81818181,
-    0x24242424,
-    0x18181818,
-    0x42424242,
-    0x81818181,
-    0x24242424,
-    0x18181818,
-    0x42424242,
-    0x81818181,
-    0x24242424,
-    0x18181818,
-    0x42424242,
-    0x81818181,
-    0x24242424,
-    0x18181818,
-    0x42424242,
-    0x81818181,
-    0x24242424,
-    0x18181818,
-    0x42424242,
-    0x81818181,
-    0x24242424,
-    0x18181818,
-    0x42424242
-  },
-  // Aspect_HS_GRID
-  {
-    0xFFFFFFFF,
-    0x88888888,
-    0xFFFFFFFF,
-    0x88888888,
-    0xFFFFFFFF,
-    0x88888888,
-    0xFFFFFFFF,
-    0x88888888,
-    0xFFFFFFFF,
-    0x88888888,
-    0xFFFFFFFF,
-    0x88888888,
-    0xFFFFFFFF,
-    0x88888888,
-    0xFFFFFFFF,
-    0x88888888,
-    0xFFFFFFFF,
-    0x88888888,
-    0xFFFFFFFF,
-    0x88888888,
-    0xFFFFFFFF,
-    0x88888888,
-    0xFFFFFFFF,
-    0x88888888,
-    0xFFFFFFFF,
-    0x88888888,
-    0xFFFFFFFF,
-    0x88888888,
-    0xFFFFFFFF,
-    0x88888888,
-    0xFFFFFFFF,
-    0x88888888
-  },
-  // Aspect_HS_GRID_WIDE
-  {
-    0xFFFFFFFF,
-    0x80808080,
-    0x80808080,
-    0x80808080,
-    0xFFFFFFFF,
-    0x80808080,
-    0x80808080,
-    0x80808080,
-    0xFFFFFFFF,
-    0x80808080,
-    0x80808080,
-    0x80808080,
-    0xFFFFFFFF,
-    0x80808080,
-    0x80808080,
-    0x80808080,
-    0xFFFFFFFF,
-    0x80808080,
-    0x80808080,
-    0x80808080,
-    0xFFFFFFFF,
-    0x80808080,
-    0x80808080,
-    0x80808080,
-    0xFFFFFFFF,
-    0x80808080,
-    0x80808080,
-    0x80808080,
-    0xFFFFFFFF,
-    0x80808080,
-    0x80808080,
-    0x80808080
-  },
-  // Aspect_HS_DIAGONAL_45
-  {
-    0x88888888,
-    0x22222222,
-    0x88888888,
-    0x22222222,
-    0x88888888,
-    0x22222222,
-    0x88888888,
-    0x22222222,
-    0x88888888,
-    0x22222222,
-    0x88888888,
-    0x22222222,
-    0x88888888,
-    0x22222222,
-    0x88888888,
-    0x22222222,
-    0x88888888,
-    0x22222222,
-    0x88888888,
-    0x22222222,
-    0x88888888,
-    0x22222222,
-    0x88888888,
-    0x22222222,
-    0x88888888,
-    0x22222222,
-    0x88888888,
-    0x22222222,
-    0x88888888,
-    0x22222222,
-    0x88888888,
-    0x22222222
-  },
-  // Aspect_HS_DIAGONAL_135
-  {
-    0x11111111,
-    0x44444444,
-    0x11111111,
-    0x44444444,
-    0x11111111,
-    0x44444444,
-    0x11111111,
-    0x44444444,
-    0x11111111,
-    0x44444444,
-    0x11111111,
-    0x44444444,
-    0x11111111,
-    0x44444444,
-    0x11111111,
-    0x44444444,
-    0x11111111,
-    0x44444444,
-    0x11111111,
-    0x44444444,
-    0x11111111,
-    0x44444444,
-    0x11111111,
-    0x44444444,
-    0x11111111,
-    0x44444444,
-    0x11111111,
-    0x44444444,
-    0x11111111,
-    0x44444444,
-    0x11111111,
-    0x44444444
-  },
-  // Aspect_HS_HORIZONTAL
-  {
-    0xFFFFFFFF,
-    0x00000000,
-    0xFFFFFFFF,
-    0x00000000,
-    0xFFFFFFFF,
-    0x00000000,
-    0xFFFFFFFF,
-    0x00000000,
-    0xFFFFFFFF,
-    0x00000000,
-    0xFFFFFFFF,
-    0x00000000,
-    0xFFFFFFFF,
-    0x00000000,
-    0xFFFFFFFF,
-    0x00000000,
-    0xFFFFFFFF,
-    0x00000000,
-    0xFFFFFFFF,
-    0x00000000,
-    0xFFFFFFFF,
-    0x00000000,
-    0xFFFFFFFF,
-    0x00000000,
-    0xFFFFFFFF,
-    0x00000000,
-    0xFFFFFFFF,
-    0x00000000,
-    0xFFFFFFFF,
-    0x00000000,
-    0xFFFFFFFF,
-    0x00000000
-  },
-  // Aspect_HS_VERTICAL
-  {
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111,
-    0x11111111
-  },
-  // Aspect_HS_DIAGONAL_45_WIDE
-  {
-    0x80808080,
-    0x20202020,
-    0x08080808,
-    0x02020202,
-    0x80808080,
-    0x20202020,
-    0x08080808,
-    0x02020202,
-    0x80808080,
-    0x20202020,
-    0x08080808,
-    0x02020202,
-    0x80808080,
-    0x20202020,
-    0x08080808,
-    0x02020202,
-    0x80808080,
-    0x20202020,
-    0x08080808,
-    0x02020202,
-    0x80808080,
-    0x20202020,
-    0x08080808,
-    0x02020202,
-    0x80808080,
-    0x20202020,
-    0x08080808,
-    0x02020202,
-    0x80808080,
-    0x20202020,
-    0x08080808,
-    0x02020202
-  },
-  // Aspect_HS_DIAGONAL_135_WIDE
-  {
-    0x01010101,
-    0x04040404,
-    0x10101010,
-    0x40404040,
-    0x01010101,
-    0x04040404,
-    0x10101010,
-    0x40404040,
-    0x01010101,
-    0x04040404,
-    0x10101010,
-    0x40404040,
-    0x01010101,
-    0x04040404,
-    0x10101010,
-    0x40404040,
-    0x01010101,
-    0x04040404,
-    0x10101010,
-    0x40404040,
-    0x01010101,
-    0x04040404,
-    0x10101010,
-    0x40404040,
-    0x01010101,
-    0x04040404,
-    0x10101010,
-    0x40404040,
-    0x01010101,
-    0x04040404,
-    0x10101010,
-    0x40404040
-  },
-  // Aspect_HS_HORIZONTAL_WIDE
-  {
-    0xFFFFFFFF,
-    0x00000000,
-    0x00000000,
-    0x00000000,
-    0xFFFFFFFF,
-    0x00000000,
-    0x00000000,
-    0x00000000,
-    0xFFFFFFFF,
-    0x00000000,
-    0x00000000,
-    0x00000000,
-    0xFFFFFFFF,
-    0x00000000,
-    0x00000000,
-    0x00000000,
-    0xFFFFFFFF,
-    0x00000000,
-    0x00000000,
-    0x00000000,
-    0xFFFFFFFF,
-    0x00000000,
-    0x00000000,
-    0x00000000,
-    0xFFFFFFFF,
-    0x00000000,
-    0x00000000,
-    0x00000000,
-    0xFFFFFFFF,
-    0x00000000,
-    0x00000000,
-    0x00000000
-  },
-  // Aspect_HS_VERTICAL_WIDE
-  {
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010,
-    0x10101010
-  }
-};
-
 // =======================================================================
 // function : OpenGl_LineAttributes
 // purpose  :
 // =======================================================================
 OpenGl_LineAttributes::OpenGl_LineAttributes()
-: myPatternBase (0),
-  myTypeOfHatch (0),
+: myTypeOfHatch (0),
   myIsEnabled (true)
 {
   //
@@ -507,49 +47,42 @@ OpenGl_LineAttributes::~OpenGl_LineAttributes()
 void OpenGl_LineAttributes::Release (OpenGl_Context* theGlCtx)
 {
   // Delete surface patterns
-  if (myPatternBase != 0)
-  {
 #if !defined(GL_ES_VERSION_2_0)
-    if (theGlCtx->IsValid())
+  if (theGlCtx != NULL && theGlCtx->IsValid())
+  {
+    for (OpenGl_MapOfHatchStylesAndIds::Iterator anIter (myStyles); anIter.More(); anIter.Next())
     {
-      theGlCtx->core11->glDeleteLists ((GLuint )myPatternBase, TEL_HS_USER_DEF_START);
+      theGlCtx->core11->glDeleteLists ((GLuint)anIter.Value(), 1);
     }
+  }
 #else
     (void )theGlCtx;
 #endif
-    myPatternBase = 0;
-  }
+    myStyles.Clear();
 }
 
 // =======================================================================
-// function : Init
+// function : init
 // purpose  :
 // =======================================================================
-void OpenGl_LineAttributes::Init (const OpenGl_Context* theGlCtx)
+unsigned int OpenGl_LineAttributes::init (const OpenGl_Context* theGlCtx,
+                                          const Handle(Graphic3d_HatchStyle)& theStyle)
 {
-  // Return if already initialized
-  if (myPatternBase != 0)
-  {
-    return;
-  }
-
 #if !defined(GL_ES_VERSION_2_0)
   if (theGlCtx->core11 == NULL)
   {
-    return;
+    return 0;
   }
 
-  // GL_POLYGON_STIPPLE need 32x32 stipple patterns
-  const int nbi = sizeof(myInteriors) / (32 * sizeof(unsigned int));
-  myPatternBase = glGenLists(TEL_HS_USER_DEF_START);
-  for (int i = 1; i < TEL_HS_USER_DEF_START; i++)
-  {
-    theGlCtx->core11->glNewList ((GLuint )myPatternBase + i, GL_COMPILE);
-    theGlCtx->core11->glPolygonStipple ((const GLubyte* )myInteriors[i < nbi ? i : 0]);
-    theGlCtx->core11->glEndList();
-  }
+  const unsigned int aListId = glGenLists(1);
+  theGlCtx->core11->glNewList ((GLuint)aListId, GL_COMPILE);
+  theGlCtx->core11->glPolygonStipple ((const GLubyte*)theStyle->Pattern());
+  theGlCtx->core11->glEndList();
+  return aListId;
 #else
   (void )theGlCtx;
+  (void )theStyle;
+  return 0;
 #endif
 }
 
@@ -557,20 +90,28 @@ void OpenGl_LineAttributes::Init (const OpenGl_Context* theGlCtx)
 // function : SetTypeOfHatch
 // purpose  :
 // =======================================================================
-int OpenGl_LineAttributes::SetTypeOfHatch (const OpenGl_Context* theGlCtx, const int theType)
+int OpenGl_LineAttributes::SetTypeOfHatch (const OpenGl_Context*               theGlCtx,
+                                           const Handle(Graphic3d_HatchStyle)& theStyle)
 {
   // Return if not initialized
-  if (myPatternBase == 0)
+  if (theStyle.IsNull())
   {
     return 0;
   }
 
   const int anOldType = myTypeOfHatch;
 
+  unsigned int aGpuListId = 0;
+  if (!myStyles.Find (theStyle, aGpuListId))
+  {
+    aGpuListId = init (theGlCtx, theStyle);
+    myStyles.Bind (theStyle, aGpuListId);
+  }
+
 #if !defined(GL_ES_VERSION_2_0)
-  if (theType != 0)
+  if (theStyle->HatchType() != 0)
   {
-    theGlCtx->core11->glCallList ((GLuint )myPatternBase + (GLuint )theType);
+    theGlCtx->core11->glCallList ((GLuint)aGpuListId);
 
     if (myIsEnabled)
     {
@@ -584,7 +125,7 @@ int OpenGl_LineAttributes::SetTypeOfHatch (const OpenGl_Context* theGlCtx, const
 #else
   (void )theGlCtx;
 #endif
-  myTypeOfHatch = theType;
+  myTypeOfHatch = theStyle->HatchType();
 
   return anOldType;
 }
@@ -597,7 +138,7 @@ bool OpenGl_LineAttributes::SetEnabled (const OpenGl_Context* theGlCtx,
                                         const bool theToEnable)
 {
   // Return if not initialized
-  if (myPatternBase == 0)
+  if (myStyles.IsEmpty())
   {
     return false;
   }
index db753ce..5247955 100644 (file)
 #include <Aspect_TypeOfLine.hxx>
 #include <Aspect_TypeOfMarker.hxx>
 #include <Font_FontAspect.hxx>
+#include <Graphic3d_HatchStyle.hxx>
+#include <NCollection_DataMap.hxx>
 
-class OpenGl_Context;
+typedef NCollection_DataMap<Handle(Graphic3d_HatchStyle), unsigned int> OpenGl_MapOfHatchStylesAndIds;
 
-#define TEL_HS_USER_DEF_START 15
+class OpenGl_Context;
 
 //! Utility class to manage OpenGL state of polygon hatching rasterization
 //! and keeping its cached state. The hatching rasterization is implemented
@@ -51,10 +53,6 @@ public:
   //! Default destructor.
   virtual ~OpenGl_LineAttributes();
 
-  //! Initialize hatch patterns as GL resources.
-  //! Call this method before using hatching.
-  void Init (const OpenGl_Context* theGlCtx);
-
   //! Release GL resources.
   virtual void Release (OpenGl_Context* theGlCtx) Standard_OVERRIDE;
 
@@ -62,7 +60,8 @@ public:
   int TypeOfHatch() const { return myTypeOfHatch; }
 
   //! Sets type of the hatch.
-  int SetTypeOfHatch (const OpenGl_Context* theGlCtx, const int theType);
+  int SetTypeOfHatch (const OpenGl_Context*               theGlCtx,
+                      const Handle(Graphic3d_HatchStyle)& theStyle);
 
   //! Current enabled state of the hatching rasterization.
   bool IsEnabled() const { return myIsEnabled; }
@@ -72,9 +71,14 @@ public:
 
 protected:
 
-  unsigned int myPatternBase; //!< Base index for predefined hatch patterns
+  unsigned int init (const OpenGl_Context* theGlCtx,
+                     const Handle(Graphic3d_HatchStyle)& theStyle);
+
+protected:
+
   int myTypeOfHatch; //!< Currently activated type of hatch
   bool myIsEnabled; //!< Current enabled state of hatching rasterization.
+  OpenGl_MapOfHatchStylesAndIds myStyles; //!< Hatch patterns
 
 public:
 
index 71b88ca..3842303 100755 (executable)
@@ -71,7 +71,7 @@ void V3d_Plane::Display (const Handle(V3d_View)& theView,
   aPlastic.SetTransparency (0.5);
   anAsp->SetFrontMaterial (aPlastic);
   anAsp->SetInteriorStyle (Aspect_IS_HATCH);
-  anAsp->SetHatchStyle (Aspect_HS_GRID_DIAGONAL_WIDE);
+  anAsp->SetHatchStyle (new Graphic3d_HatchStyle (Aspect_HS_GRID_DIAGONAL_WIDE));
   aGroup->SetGroupPrimitivesAspect (anAsp);
 
   const Standard_ShortReal aSize = (Standard_ShortReal)(0.5*aViewer->DefaultViewSize());
index f31e19c..9c6297e 100644 (file)
@@ -1478,6 +1478,10 @@ struct ViewerTest_AspectsChangeSet
   Standard_Integer         SelectionMode;
   Standard_Integer         Sensitivity;
 
+  Standard_Integer         ToSetHatch;
+  Standard_Integer         StdHatchStyle;
+  TCollection_AsciiString  PathToHatchPattern;
+
   //! Empty constructor
   ViewerTest_AspectsChangeSet()
   : ToSetVisibility   (0),
@@ -1502,7 +1506,10 @@ struct ViewerTest_AspectsChangeSet
     MaxParamValue (500000),
     ToSetSensitivity (0),
     SelectionMode (-1),
-    Sensitivity (-1) {}
+    Sensitivity (-1),
+    ToSetHatch (0),
+    StdHatchStyle (-1)
+    {}
 
   //! @return true if no changes have been requested
   Standard_Boolean IsEmpty() const
@@ -1516,7 +1523,8 @@ struct ViewerTest_AspectsChangeSet
         && ToSetFreeBoundaryColor == 0
         && ToSetFreeBoundaryWidth == 0
         && ToSetMaxParamValue     == 0
-        && ToSetSensitivity       == 0;
+        && ToSetSensitivity       == 0
+        && ToSetHatch             == 0;
   }
 
   //! @return true if properties are valid
@@ -1568,6 +1576,11 @@ struct ViewerTest_AspectsChangeSet
       std::cout << "Error: sensitivity parameter value should be positive (specified " << Sensitivity << ")\n";
       isOk = Standard_False;
     }
+    if (ToSetHatch == 1 && StdHatchStyle < 0 && PathToHatchPattern == "")
+    {
+      std::cout << "Error: hatch style must be specified\n";
+      isOk = Standard_False;
+    }
     return isOk;
   }
 
@@ -2096,6 +2109,9 @@ static Standard_Integer VAspects (Draw_Interpretor& /*theDI*/,
       aChangeSet->FreeBoundaryColor = DEFAULT_FREEBOUNDARY_COLOR;
       aChangeSet->ToSetFreeBoundaryWidth = -1;
       aChangeSet->FreeBoundaryWidth = 1.0;
+      aChangeSet->ToSetHatch = -1;
+      aChangeSet->StdHatchStyle = -1;
+      aChangeSet->PathToHatchPattern.Clear();
     }
     else if (anArg == "-isoontriangulation"
           || anArg == "-isoontriang")
@@ -2156,6 +2172,31 @@ static Standard_Integer VAspects (Draw_Interpretor& /*theDI*/,
       aChangeSet->SelectionMode = Draw::Atoi (theArgVec[++anArgIter]);
       aChangeSet->Sensitivity = Draw::Atoi (theArgVec[++anArgIter]);
     }
+    else if (anArg == "-sethatch")
+    {
+      if (isDefaults)
+      {
+        std::cout << "Error: wrong syntax. -setHatch can not be used together with -defaults call!\n";
+        return 1;
+      }
+
+      if (aNames.IsEmpty())
+      {
+        std::cout << "Error: object should be specified explicitly when -setHatch is used!\n";
+        return 1;
+      }
+
+      aChangeSet->ToSetHatch = 1;
+      TCollection_AsciiString anArg (theArgVec[++anArgIter]);
+      if (anArg.Length() <= 2)
+      {
+        aChangeSet->StdHatchStyle = Draw::Atoi (anArg.ToCString());
+      }
+      else
+      {
+        aChangeSet->PathToHatchPattern = anArg;
+      }
+    }
     else
     {
       std::cout << "Error: wrong syntax at " << anArg << "\n";
@@ -2381,6 +2422,42 @@ static Standard_Integer VAspects (Draw_Interpretor& /*theDI*/,
         {
           aDrawer->SetMaximalParameterValue (aChangeSet->MaxParamValue);
         }
+        if (aChangeSet->ToSetHatch != 0)
+        {
+          if (!aDrawer->HasOwnShadingAspect())
+          {
+            aDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
+            *aDrawer->ShadingAspect()->Aspect() = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
+          }
+
+          Handle(Graphic3d_AspectFillArea3d) anAsp = aDrawer->ShadingAspect()->Aspect();
+          if (aChangeSet->ToSetHatch == -1)
+          {
+            anAsp->SetInteriorStyle (Aspect_IS_SOLID);
+          }
+          else
+          {
+            anAsp->SetInteriorStyle (Aspect_IS_HATCH);
+            if (!aChangeSet->PathToHatchPattern.IsEmpty())
+            {
+              Handle(Image_AlienPixMap) anImage = new Image_AlienPixMap();
+              if (anImage->Load (TCollection_AsciiString (aChangeSet->PathToHatchPattern.ToCString())))
+              {
+                anAsp->SetHatchStyle (new Graphic3d_HatchStyle (anImage));
+              }
+              else
+              {
+                std::cout << "Error: cannot load the following image: " << aChangeSet->PathToHatchPattern << std::endl;
+                return 1;
+              }
+            }
+            else if (aChangeSet->StdHatchStyle != -1)
+            {
+              anAsp->SetHatchStyle (new Graphic3d_HatchStyle ((Aspect_HatchStyle)aChangeSet->StdHatchStyle));
+            }
+          }
+          toRedisplay = Standard_True;
+        }
       }
 
       for (aChangesIter.Next(); aChangesIter.More(); aChangesIter.Next())
diff --git a/tests/bugs/vis/bug28107 b/tests/bugs/vis/bug28107
new file mode 100644 (file)
index 0000000..0e80ff7
--- /dev/null
@@ -0,0 +1,18 @@
+puts "==========="
+puts "OCC28107"
+puts "==========="
+puts ""
+##########################################################################
+# Visualization - provide a flexible interface to set custom hatch styles
+##########################################################################
+
+pload VISUALIZATION MODELING
+
+box b 1 1 1
+
+vinit View1
+vdisplay b -dispMode 1
+vfit
+
+vaspects b -setHatch 4
+vdump $imagedir/${casename}_hatch.png