From d246a238b2d5e8daa63bc63386752567a42df732 Mon Sep 17 00:00:00 2001
From: Charles Gueunet <charles.gueunet@kitware.com>
Date: Fri, 10 Sep 2021 09:35:11 +0200
Subject: [PATCH] Introduce a new HyperTreeGrid mapper

This mapper may take advantage of the vtkAdaptiveDataSetSurfaceFilter to
extract and render only the part of the HTG in the camera frustum.
This version only works on 2D as of today.
---
 Common/ExecutionModel/vtkAlgorithm.cxx        |   1 -
 Documentation/release/dev/add-HTGMapper.md    |   3 +
 .../vtkAdaptiveDataSetSurfaceFilter.cxx       |  45 -----
 .../Hybrid/vtkAdaptiveDataSetSurfaceFilter.h  |   8 -
 Rendering/Core/vtk.module                     |   1 -
 Rendering/Core/vtkPolyDataMapper.cxx          |   1 -
 Rendering/Core/vtkPolyDataMapper.h            |   2 +-
 Rendering/HyperTree/vtkHyperTreeGridMapper.h  |  80 ---------
 .../CMakeLists.txt                            |   2 +-
 .../{HyperTree => HyperTreeGrid}/vtk.module   |   6 +-
 .../vtkHyperTreeGridMapper.cxx                | 111 +++++++------
 .../HyperTreeGrid/vtkHyperTreeGridMapper.h    | 154 ++++++++++++++++++
 Rendering/OpenGL2/CMakeLists.txt              |   2 +
 Rendering/OpenGL2/vtk.module                  |   1 +
 .../OpenGL2/vtkOpenGLHyperTreeGridMapper.cxx  |  34 ++++
 .../OpenGL2/vtkOpenGLHyperTreeGridMapper.h    |  49 ++++++
 Rendering/OpenGL2/vtkOpenGLPolyDataMapper.cxx |   7 -
 17 files changed, 310 insertions(+), 197 deletions(-)
 create mode 100644 Documentation/release/dev/add-HTGMapper.md
 delete mode 100644 Rendering/HyperTree/vtkHyperTreeGridMapper.h
 rename Rendering/{HyperTree => HyperTreeGrid}/CMakeLists.txt (80%)
 rename Rendering/{HyperTree => HyperTreeGrid}/vtk.module (72%)
 rename Rendering/{HyperTree => HyperTreeGrid}/vtkHyperTreeGridMapper.cxx (53%)
 create mode 100644 Rendering/HyperTreeGrid/vtkHyperTreeGridMapper.h
 create mode 100644 Rendering/OpenGL2/vtkOpenGLHyperTreeGridMapper.cxx
 create mode 100644 Rendering/OpenGL2/vtkOpenGLHyperTreeGridMapper.h

diff --git a/Common/ExecutionModel/vtkAlgorithm.cxx b/Common/ExecutionModel/vtkAlgorithm.cxx
index a4686cfd69a..c6e98e62f74 100644
--- a/Common/ExecutionModel/vtkAlgorithm.cxx
+++ b/Common/ExecutionModel/vtkAlgorithm.cxx
@@ -230,7 +230,6 @@ void vtkAlgorithm::SetInputArrayToProcess(int idx, vtkInformation* inInfo)
 void vtkAlgorithm::SetInputArrayToProcess(
   int idx, int port, int connection, int fieldAssociation, int attributeType)
 {
-  std::cout << "vtkAlgorithm::SetInputArrayToProcess " << this->GetClassName() << std::endl;
   vtkInformation* info = this->GetInputArrayInformation(idx);
 
   info->Set(INPUT_PORT(), port);
diff --git a/Documentation/release/dev/add-HTGMapper.md b/Documentation/release/dev/add-HTGMapper.md
new file mode 100644
index 00000000000..b2f7a01b9ea
--- /dev/null
+++ b/Documentation/release/dev/add-HTGMapper.md
@@ -0,0 +1,3 @@
+# Add vtkHyperTreeGridMapper
+
+A new HyperTree Grid mapper has been introduced for 2D HTG, able to only render the part visible in the camera frustum
diff --git a/Filters/Hybrid/vtkAdaptiveDataSetSurfaceFilter.cxx b/Filters/Hybrid/vtkAdaptiveDataSetSurfaceFilter.cxx
index e1b13df786e..9670bdcdb51 100644
--- a/Filters/Hybrid/vtkAdaptiveDataSetSurfaceFilter.cxx
+++ b/Filters/Hybrid/vtkAdaptiveDataSetSurfaceFilter.cxx
@@ -302,22 +302,6 @@ int vtkAdaptiveDataSetSurfaceFilter::DataObjectExecute(vtkDataObject* inputDS, v
     this->WindowBounds[1] = this->LastCameraFocalPoint[0] + cam->GetParallelScale() * ratio;
     this->WindowBounds[2] = this->LastCameraFocalPoint[1] - cam->GetParallelScale();
     this->WindowBounds[3] = this->LastCameraFocalPoint[1] + cam->GetParallelScale();
-
-#ifndef NDEBUG
-    this->NbRejectByCircle = 0;
-    this->NbRejectByBB = 0;
-
-    std::cerr << "LevelMax        " << this->LevelMax << std::endl;
-    std::cerr << "CircleSelection " << this->CircleSelection << std::endl;
-    std::cerr << "Circle R        " << this->Radius << std::endl;
-    std::cerr << "       CX       " << this->LastCameraFocalPoint[this->Axis1] << std::endl;
-    std::cerr << "       CY       " << this->LastCameraFocalPoint[this->Axis2] << std::endl;
-    std::cerr << "BBSelection     " << this->BBSelection << std::endl;
-    std::cerr << "Bounds X        " << this->WindowBounds[0] << " : " << this->WindowBounds[1]
-              << std::endl;
-    std::cerr << "       Y        " << this->WindowBounds[2] << " : " << this->WindowBounds[3]
-              << std::endl;
-#endif
   }
   else
   {
@@ -423,25 +407,6 @@ void vtkAdaptiveDataSetSurfaceFilter::ProcessTrees(vtkHyperTreeGrid* input, vtkP
     output->SetPolys(this->Cells);
   }
 
-#ifndef NDEBUG
-  std::cerr << "vtkAdaptiveDataSetSurfaceFilter #Points            "
-            << this->Points->GetNumberOfPoints() << std::endl;
-  std::cerr << "                                #Cells             "
-            << this->Cells->GetNumberOfCells() << std::endl;
-  std::cerr << "                                #Type&Connectivity "
-            << this->Cells->GetNumberOfConnectivityIds() << std::endl;
-  std::cerr << "                          Cells #NbRejectByBB      " << this->NbRejectByBB
-            << std::endl;
-  std::cerr << "                                #NbRejectByCircle  " << this->NbRejectByCircle
-            << std::endl;
-#endif
-  std::cerr << "vtkAdaptiveDataSetSurfaceFilter #Points            "
-            << this->Points->GetNumberOfPoints() << std::endl;
-  std::cerr << "                                #Cells             "
-            << this->Cells->GetNumberOfCells() << std::endl;
-  std::cerr << "                                #Type&Connectivity "
-            << this->Cells->GetNumberOfConnectivityIds() << std::endl;
-
   this->Points->Delete();
   this->Points = nullptr;
   this->Cells->Delete();
@@ -499,16 +464,6 @@ void vtkAdaptiveDataSetSurfaceFilter::RecursivelyProcessTreeNot3D(
         (originAxis1 <= this->WindowBounds[1]) &&
         (originAxis2 + 2 * halfAxis2 >= this->WindowBounds[2]) &&
         (originAxis2 <= this->WindowBounds[3]));
-#ifndef NDEBUG
-      if (!insideBB)
-      {
-        this->NbRejectByBB++;
-      }
-    }
-    else
-    {
-      this->NbRejectByCircle++;
-#endif
     }
   }
   if (insideBB)
diff --git a/Filters/Hybrid/vtkAdaptiveDataSetSurfaceFilter.h b/Filters/Hybrid/vtkAdaptiveDataSetSurfaceFilter.h
index 5d128069306..c6aa2f38de3 100644
--- a/Filters/Hybrid/vtkAdaptiveDataSetSurfaceFilter.h
+++ b/Filters/Hybrid/vtkAdaptiveDataSetSurfaceFilter.h
@@ -251,14 +251,6 @@ protected:
    */
   bool BBSelection;
 
-#ifndef NDEBUG
-  /**
-   * Effect of options selection
-   */
-  long int NbRejectByCircle;
-  long int NbRejectByBB;
-#endif
-
   /**
    * JB Forced, fixed the level depth, ignored automatic determination
    */
diff --git a/Rendering/Core/vtk.module b/Rendering/Core/vtk.module
index dde12fe7849..bbfdb6a9919 100644
--- a/Rendering/Core/vtk.module
+++ b/Rendering/Core/vtk.module
@@ -13,7 +13,6 @@ DEPENDS
   VTK::CommonExecutionModel
   VTK::CommonMath
   VTK::FiltersCore
-  VTK::FiltersHyperTree
 PRIVATE_DEPENDS
   VTK::CommonColor
   VTK::CommonComputationalGeometry
diff --git a/Rendering/Core/vtkPolyDataMapper.cxx b/Rendering/Core/vtkPolyDataMapper.cxx
index 51a05f13f0b..8f2be312e84 100644
--- a/Rendering/Core/vtkPolyDataMapper.cxx
+++ b/Rendering/Core/vtkPolyDataMapper.cxx
@@ -41,7 +41,6 @@ void vtkPolyDataMapper::Render(vtkRenderer* ren, vtkActor* act)
 {
   if (this->Static)
   {
-    std::cout << "RenderPiece" << std::endl;
     this->RenderPiece(ren, act);
     return;
   }
diff --git a/Rendering/Core/vtkPolyDataMapper.h b/Rendering/Core/vtkPolyDataMapper.h
index 2db168fc9d6..e1f9b14a7e9 100644
--- a/Rendering/Core/vtkPolyDataMapper.h
+++ b/Rendering/Core/vtkPolyDataMapper.h
@@ -55,7 +55,7 @@ public:
    * Specify the input data to map.
    */
   void SetInputData(vtkPolyData* in);
-  virtual vtkPolyData* GetInput();
+  vtkPolyData* GetInput();
   ///@}
 
   ///@{
diff --git a/Rendering/HyperTree/vtkHyperTreeGridMapper.h b/Rendering/HyperTree/vtkHyperTreeGridMapper.h
deleted file mode 100644
index 794a2adf5fd..00000000000
--- a/Rendering/HyperTree/vtkHyperTreeGridMapper.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*=========================================================================
-
-  Program:   Visualization Toolkit
-  Module:    vtkHyperTreeGridMapper.h
-
-  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
-  All rights reserved.
-  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
-
-     This software is distributed WITHOUT ANY WARRANTY; without even
-     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-     PURPOSE.  See the above copyright notice for more information.
-
-=========================================================================*/
-/**
- * @class   vtkHyperTreeGridMapper
- * @brief   map vtkHyperTreeGrid to graphics primitives
- *
- * vtkHyperTreeGridMapper is a class that maps polygonal data (i.e., vtkHyperTreeGrid)
- * to graphics primitives. vtkHyperTreeGridMapper serves as a superclass for
- * device-specific poly data mappers, that actually do the mapping to the
- * rendering/graphics hardware/software.
- */
-
-#ifndef vtkHyperTreeGridMapper_h
-#define vtkHyperTreeGridMapper_h
-
-#include "vtkOpenGLPolyDataMapper.h"
-#include "vtkPolyDataMapper.h"           // For internal mapper
-#include "vtkRenderingHyperTreeModule.h" // For export macro
-#include "vtkSmartPointer.h"             // For vtkSmartPointer
-
-class vtkAdaptiveDataSetSurfaceFilter;
-class vtkHyperTreeGrid;
-class vtkHyperTreeGridGeometry;
-class vtkRenderer;
-class vtkRenderWindow;
-
-class VTKRENDERINGHYPERTREE_EXPORT vtkHyperTreeGridMapper : public vtkOpenGLPolyDataMapper
-{
-public:
-  static vtkHyperTreeGridMapper* New();
-  vtkTypeMacro(vtkHyperTreeGridMapper, vtkOpenGLPolyDataMapper);
-  void PrintSelf(ostream& os, vtkIndent indent) override;
-
-  using Superclass::SetInputConnection;
-  void SetInputConnection(vtkAlgorithmOutput* input) override;
-
-  /**
-   * This calls RenderPiece (in a for loop if streaming is necessary).
-   */
-  void Render(vtkRenderer* ren, vtkActor* act) override;
-
-  //@{
-  /**
-   * Specify the input data to map.
-   */
-  void SetInputData(vtkHyperTreeGrid* in);
-  vtkPolyData* GetInput() override;
-  //@}
-
-  using Superclass::Update;
-  void Update(int port) override;
-
-  int FillInputPortInformation(int port, vtkInformation* info) override;
-
-protected:
-  vtkHyperTreeGridMapper();
-  ~vtkHyperTreeGridMapper() override = default;
-
-private:
-  vtkSmartPointer<vtkHyperTreeGridGeometry> GeometryFilter;
-  vtkSmartPointer<vtkAdaptiveDataSetSurfaceFilter> Adaptive2DGeometryFilter;
-  bool UseLOD;
-
-  vtkHyperTreeGridMapper(const vtkHyperTreeGridMapper&) = delete;
-  void operator=(const vtkHyperTreeGridMapper&) = delete;
-};
-
-#endif
diff --git a/Rendering/HyperTree/CMakeLists.txt b/Rendering/HyperTreeGrid/CMakeLists.txt
similarity index 80%
rename from Rendering/HyperTree/CMakeLists.txt
rename to Rendering/HyperTreeGrid/CMakeLists.txt
index e45fc4613e3..6e19050821e 100644
--- a/Rendering/HyperTree/CMakeLists.txt
+++ b/Rendering/HyperTreeGrid/CMakeLists.txt
@@ -1,7 +1,7 @@
 set(classes
   vtkHyperTreeGridMapper)
 
-vtk_module_add_module(VTK::RenderingHyperTree
+vtk_module_add_module(VTK::RenderingHyperTreeGrid
   CLASSES ${classes}
   )
 
diff --git a/Rendering/HyperTree/vtk.module b/Rendering/HyperTreeGrid/vtk.module
similarity index 72%
rename from Rendering/HyperTree/vtk.module
rename to Rendering/HyperTreeGrid/vtk.module
index ef922b10287..e439b65cdfe 100644
--- a/Rendering/HyperTree/vtk.module
+++ b/Rendering/HyperTreeGrid/vtk.module
@@ -1,7 +1,7 @@
 NAME
-  VTK::RenderingHyperTree
+  VTK::RenderingHyperTreeGrid
 LIBRARY_NAME
-  vtkRenderingHyperTree
+  vtkRenderingHyperTreeGrid
 IMPLEMENTABLE
 KIT
   VTK::Rendering
@@ -14,4 +14,4 @@ DEPENDS
   VTK::CommonMath
   VTK::FiltersHybrid
   VTK::FiltersHyperTree
-  VTK::RenderingOpenGL2
+  VTK::RenderingCore
diff --git a/Rendering/HyperTree/vtkHyperTreeGridMapper.cxx b/Rendering/HyperTreeGrid/vtkHyperTreeGridMapper.cxx
similarity index 53%
rename from Rendering/HyperTree/vtkHyperTreeGridMapper.cxx
rename to Rendering/HyperTreeGrid/vtkHyperTreeGridMapper.cxx
index 12ca05086e4..f8022274689 100644
--- a/Rendering/HyperTree/vtkHyperTreeGridMapper.cxx
+++ b/Rendering/HyperTreeGrid/vtkHyperTreeGridMapper.cxx
@@ -26,70 +26,85 @@
 #include "vtkRenderWindow.h"
 #include "vtkStreamingDemandDrivenPipeline.h"
 
+#include "vtkActor.h"
+#include "vtkCellData.h"
+#include "vtkPointData.h"
+#include "vtkProperty.h"
+
 vtkObjectFactoryNewMacro(vtkHyperTreeGridMapper);
 
 //------------------------------------------------------------------------------
-vtkHyperTreeGridMapper::vtkHyperTreeGridMapper()
-  : GeometryFilter(vtkSmartPointer<vtkHyperTreeGridGeometry>::New())
-  , Adaptive2DGeometryFilter(vtkSmartPointer<vtkAdaptiveDataSetSurfaceFilter>::New())
-  , UseLOD(false)
-{
-}
+vtkHyperTreeGridMapper::vtkHyperTreeGridMapper() = default;
+
+//------------------------------------------------------------------------------
+vtkHyperTreeGridMapper::~vtkHyperTreeGridMapper() = default;
 
 //------------------------------------------------------------------------------
 void vtkHyperTreeGridMapper::Render(vtkRenderer* ren, vtkActor* act)
 {
-  std::cout << "vtkHyperTreeGridMapper::Render " << std::endl;
-  if (this->UseLOD)
-  {
-    this->Adaptive2DGeometryFilter->SetRenderer(ren);
-    this->Adaptive2DGeometryFilter->Update();
-  }
-  else
-  {
-    this->GeometryFilter->SetInputArrayToProcess(
-      0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_CELLS, "Depth");
-    this->GeometryFilter->Update();
+  if (this->GetMTime() > this->PDMapper->GetMTime())
+  { // forward common internal properties
+    this->PDMapper->ShallowCopy(this);
+    this->PDMapper->SetInputData(this->GetSurfaceFilterInput());
   }
 
-  this->SelectColorArray("Depth");
-  if (this->GetScalarMode() == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA)
-  {
-    std::cout << "COOL " << std::endl;
-  }
-  else
-  {
-    std::cout << "PAS COOL " << std::endl;
-  }
-  this->Superclass::Render(ren, act);
+  this->PDMapper->Render(ren, act);
+}
+
+//------------------------------------------------------------------------------
+void vtkHyperTreeGridMapper::SetInputConnection(vtkAlgorithmOutput* input)
+{
+  this->GeometryFilter->SetInputConnection(input);
+  this->Adaptive2DGeometryFilter->SetInputConnection(input);
+  this->Superclass::SetInputConnection(input);
 }
 
 //------------------------------------------------------------------------------
-void vtkHyperTreeGridMapper::SetInputData(vtkHyperTreeGrid* input)
+void vtkHyperTreeGridMapper::SetInputDataObject(int port, vtkDataObject* input)
 {
-  this->GeometryFilter->SetInputData(input);
-  this->Adaptive2DGeometryFilter->SetInputData(input);
-  this->Superclass::SetInputDataObject(input);
+  this->GeometryFilter->SetInputDataObject(input);
+  this->Adaptive2DGeometryFilter->SetInputDataObject(input);
+  this->Superclass::SetInputDataObject(port, input);
+}
+
+//------------------------------------------------------------------------------
+void vtkHyperTreeGridMapper::SetInputDataObject(vtkDataObject* input)
+{
+  this->SetInputDataObject(0, input);
+}
+
+//------------------------------------------------------------------------------
+double* vtkHyperTreeGridMapper::GetBounds()
+{
+  return this->GetSurfaceFilterInput()->GetBounds();
+}
+
+//------------------------------------------------------------------------------
+void vtkHyperTreeGridMapper::GetBounds(double bounds[6])
+{
+  this->GetSurfaceFilterInput()->GetBounds(bounds);
 }
 
 //------------------------------------------------------------------------------
 // Specify the input data or filter.
-vtkPolyData* vtkHyperTreeGridMapper::GetInput()
+vtkPolyData* vtkHyperTreeGridMapper::GetSurfaceFilterInput()
 {
-  this->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_CELLS, "Depth");
-  this->GeometryFilter->SetInputArrayToProcess(
-    0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_CELLS, "Depth");
-  this->Update();
-  this->GeometryFilter->Update();
-  return this->UseLOD
-    ? vtkPolyData::SafeDownCast(this->Adaptive2DGeometryFilter->GetOutputDataObject(0))
-    : vtkPolyData::SafeDownCast(this->GeometryFilter->GetOutputDataObject(0));
+  vtkAlgorithm* geometry = this->GetSurfaceFilter();
+  if (geometry->GetInputDataObject(0, 0))
+  {
+    geometry->Update();
+  }
+  return vtkPolyData::SafeDownCast(geometry->GetOutputDataObject(0));
 }
 
 //------------------------------------------------------------------------------
 void vtkHyperTreeGridMapper::PrintSelf(ostream& os, vtkIndent indent)
 {
   this->Superclass::PrintSelf(os, indent);
+  os << indent << "UseCameraFrustum: " << this->UseCameraFrustum << std::endl;
+  this->GetSurfaceFilter()->PrintSelf(os, indent.GetNextIndent());
+  os << indent << "Internal PolyData Mapper: " << std::endl;
+  this->PDMapper->PrintSelf(os, indent.GetNextIndent());
 }
 
 //------------------------------------------------------------------------------
@@ -100,23 +115,21 @@ int vtkHyperTreeGridMapper::FillInputPortInformation(int vtkNotUsed(port), vtkIn
 }
 
 //------------------------------------------------------------------------------
-void vtkHyperTreeGridMapper::SetInputConnection(vtkAlgorithmOutput* input)
+void vtkHyperTreeGridMapper::Update(int port)
 {
-  this->GeometryFilter->SetInputConnection(input);
-  this->Adaptive2DGeometryFilter->SetInputConnection(input);
-  this->Superclass::SetInputConnection(input);
+  this->Superclass::Update(port);
+  this->GetSurfaceFilter()->Update();
 }
 
 //------------------------------------------------------------------------------
-void vtkHyperTreeGridMapper::Update(int port)
+vtkAlgorithm* vtkHyperTreeGridMapper::GetSurfaceFilter()
 {
-  this->Superclass::Update(port);
-  if (!this->UseLOD)
+  if (this->UseCameraFrustum)
   {
-    this->GeometryFilter->Update();
+    return this->Adaptive2DGeometryFilter;
   }
   else
   {
-    this->Adaptive2DGeometryFilter->Update();
+    return this->GeometryFilter;
   }
 }
diff --git a/Rendering/HyperTreeGrid/vtkHyperTreeGridMapper.h b/Rendering/HyperTreeGrid/vtkHyperTreeGridMapper.h
new file mode 100644
index 00000000000..89c2958e497
--- /dev/null
+++ b/Rendering/HyperTreeGrid/vtkHyperTreeGridMapper.h
@@ -0,0 +1,154 @@
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    vtkHyperTreeGridMapper.h
+
+  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
+  All rights reserved.
+  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+/**
+ * @class   vtkHyperTreeGridMapper
+ * @brief   map vtkHyperTreeGrid to graphics primitives
+ *
+ * vtkHyperTreeGridMapper is a class that maps polygonal data (i.e., vtkHyperTreeGrid)
+ * to graphics primitives. vtkHyperTreeGridMapper serves as a superclass for
+ * device-specific poly data mappers, that actually do the mapping to the
+ * rendering/graphics hardware/software.
+ *
+ * Note: this class has its own module to avoid cyclic dependency between Rendering Core
+ * and Filters Hybrid
+ * * It need Filters Hybrid for Adaptive2DGeometryFilter
+ * * Filters Hybrid need Rendering Core because of Adaptive2DGeometryFilter
+ */
+
+#ifndef vtkHyperTreeGridMapper_h
+#define vtkHyperTreeGridMapper_h
+
+#include "vtkMapper.h"       // For internal mapper
+#include "vtkSetGet.h"       // Get macro
+#include "vtkSmartPointer.h" // For vtkSmartPointer
+
+#include "vtkRenderingHyperTreeGridModule.h" // For export macro
+
+class vtkAdaptiveDataSetSurfaceFilter;
+class vtkHyperTreeGrid;
+class vtkHyperTreeGridGeometry;
+class vtkPolyData;
+class vtkPolyDataMapper;
+class vtkRenderWindow;
+class vtkRenderer;
+
+class VTKRENDERINGHYPERTREEGRID_EXPORT vtkHyperTreeGridMapper : public vtkMapper
+{
+public:
+  static vtkHyperTreeGridMapper* New();
+  vtkTypeMacro(vtkHyperTreeGridMapper, vtkMapper);
+  void PrintSelf(ostream& os, vtkIndent indent) override;
+
+  //@{
+  /**
+   * Set the connection for the given input port index.  Each input
+   * port of a filter has a specific purpose.  A port may have zero or
+   * more connections and the required number is specified by each
+   * filter.  Setting the connection with this method removes all
+   * other connections from the port.  To add more than one connection
+   * use AddInputConnection().
+
+   * The input for the connection is the output port of another
+   * filter, which is obtained with GetOutputPort().  Typical usage is
+
+   * filter2->SetInputConnection(0, filter1->GetOutputPort(0)).
+
+   * \link vtkAlgorithm
+   */
+  using Superclass::SetInputConnection;
+  void SetInputConnection(vtkAlgorithmOutput* input) override;
+  void SetInputDataObject(int port, vtkDataObject* input) override;
+  void SetInputDataObject(vtkDataObject* input) override;
+  //@}
+
+  //@{
+  /**
+   * For this mapper, the bounds correspond to the output for the
+   * internal surface filter which may be restricted to the Camera frustum
+   * if UseCameraFrustum is on.
+   */
+  double* GetBounds() override;
+  void GetBounds(double bounds[6]) override;
+  //@}
+
+  //@{
+  /**
+   * This boolean control whether or not the mapping should adapt
+   * to the Camera frustum during the rendering. Setting this variable
+   * to true (default) should provide increased preformances.
+   */
+  vtkGetMacro(UseCameraFrustum, bool);
+  vtkSetMacro(UseCameraFrustum, bool);
+  vtkBooleanMacro(UseCameraFrustum, bool);
+  //@}
+
+  /**
+   * Use the internal PolyData Mapper to do the rendering
+   * of the HTG transformed by the current SurfaceFilter:
+   * * Adaptive2DGeometryFilter if UseCameraFrustum
+   * * GeometryFilter otherwise
+   */
+  void Render(vtkRenderer* ren, vtkActor* act) override;
+
+  //@{
+  /**
+   * Bring this algorithm's outputs up-to-date.
+
+   * \link vtkAlgorithm
+   */
+  using Superclass::Update;
+  void Update(int port) override;
+  //@}
+
+  /**
+   * Fill the input port information objects for this algorithm.  This
+   * is invoked by the first call to GetInputPortInformation for each
+   * port so subclasses can specify what they can handle.
+
+   * \link vtkAlgorithm
+   */
+  int FillInputPortInformation(int port, vtkInformation* info) override;
+
+  /**
+   * Get the underlingin suface fileter, used to transfom the input HTG
+   * to a PolyData that will be rendered using the PDMapper.
+   */
+  vtkAlgorithm* GetSurfaceFilter();
+
+protected:
+  vtkHyperTreeGridMapper();
+  virtual ~vtkHyperTreeGridMapper();
+
+  /**
+   * The input exposed here is the output of the SurfaceFilter.
+   * It is the piece of PolyData to map and render on the screen.
+   */
+  vtkPolyData* GetSurfaceFilterInput();
+
+  // Generate the surface to render
+  bool UseCameraFrustum = true;
+  vtkNew<vtkHyperTreeGridGeometry> GeometryFilter;
+  vtkNew<vtkAdaptiveDataSetSurfaceFilter> Adaptive2DGeometryFilter;
+
+  // render the extracted surface, need to be created
+  // in device specific subclass
+  vtkSmartPointer<vtkPolyDataMapper> PDMapper;
+
+private:
+  vtkHyperTreeGridMapper(const vtkHyperTreeGridMapper&) = delete;
+  void operator=(const vtkHyperTreeGridMapper&) = delete;
+};
+
+#endif
diff --git a/Rendering/OpenGL2/CMakeLists.txt b/Rendering/OpenGL2/CMakeLists.txt
index 090042aa951..662e052f557 100644
--- a/Rendering/OpenGL2/CMakeLists.txt
+++ b/Rendering/OpenGL2/CMakeLists.txt
@@ -33,6 +33,7 @@ set(classes
   vtkOpenGLGlyph3DMapper
   vtkOpenGLHardwareSelector
   vtkOpenGLHelper
+  vtkOpenGLHyperTreeGridMapper
   vtkOpenGLImageAlgorithmHelper
   vtkOpenGLImageMapper
   vtkOpenGLImageSliceMapper
@@ -186,6 +187,7 @@ set(opengl_overrides
   ImageMapper
   ImageSliceMapper
   Glyph3DMapper
+  HyperTreeGridMapper
   Light
   PointGaussianMapper
   PolyDataMapper
diff --git a/Rendering/OpenGL2/vtk.module b/Rendering/OpenGL2/vtk.module
index 58a5de6f836..331f7fd8b25 100644
--- a/Rendering/OpenGL2/vtk.module
+++ b/Rendering/OpenGL2/vtk.module
@@ -14,6 +14,7 @@ DEPENDS
   VTK::CommonDataModel
   VTK::FiltersGeneral
   VTK::RenderingCore
+  VTK::RenderingHyperTreeGrid
   VTK::RenderingUI
   VTK::glew
 PRIVATE_DEPENDS
diff --git a/Rendering/OpenGL2/vtkOpenGLHyperTreeGridMapper.cxx b/Rendering/OpenGL2/vtkOpenGLHyperTreeGridMapper.cxx
new file mode 100644
index 00000000000..2e211a4955a
--- /dev/null
+++ b/Rendering/OpenGL2/vtkOpenGLHyperTreeGridMapper.cxx
@@ -0,0 +1,34 @@
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    vtkOpenGLHyperTreeGridMapper.cxx
+
+  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
+  All rights reserved.
+  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+#include "vtkOpenGLHyperTreeGridMapper.h"
+
+#include "vtkObjectFactory.h"
+#include "vtkOpenGLPolyDataMapper.h"
+
+vtkObjectFactoryNewMacro(vtkOpenGLHyperTreeGridMapper);
+
+//------------------------------------------------------------------------------
+vtkOpenGLHyperTreeGridMapper::vtkOpenGLHyperTreeGridMapper()
+  : vtkHyperTreeGridMapper()
+{
+  this->PDMapper = vtkSmartPointer<vtkOpenGLPolyDataMapper>::New();
+}
+
+//------------------------------------------------------------------------------
+void vtkOpenGLHyperTreeGridMapper::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os, indent);
+  os << "internal mapper: " << indent << this->PDMapper;
+}
diff --git a/Rendering/OpenGL2/vtkOpenGLHyperTreeGridMapper.h b/Rendering/OpenGL2/vtkOpenGLHyperTreeGridMapper.h
new file mode 100644
index 00000000000..bdb3e2d88ee
--- /dev/null
+++ b/Rendering/OpenGL2/vtkOpenGLHyperTreeGridMapper.h
@@ -0,0 +1,49 @@
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    vtkOpenGLHyperTreeGridMapper.h
+
+  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
+  All rights reserved.
+  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+/**
+ * @class   vtkOpenGLHyperTreeGridMapper
+ * @brief   map vtkHyperTreeGrid to graphics primitives
+ *
+ * vtkOpenGLHyperTreeGridMapper is a class that uses OpenGL to do the actual
+ * rendering of Hyper Tree Grid.
+ * For now, only support 2D HTG.
+ */
+
+#ifndef vtkOpenGLHyperTreeGridMapper_h
+#define vtkOpenGLHyperTreeGridMapper_h
+
+#include "vtkHyperTreeGridMapper.h" // For internal mapper
+#include "vtkSetGet.h"              // Get macro
+#include "vtkSmartPointer.h"        // For vtkSmartPointer
+
+#include "vtkRenderingOpenGL2Module.h" // For export macro
+
+class VTKRENDERINGOPENGL2_EXPORT vtkOpenGLHyperTreeGridMapper : public vtkHyperTreeGridMapper
+{
+public:
+  static vtkOpenGLHyperTreeGridMapper* New();
+  vtkTypeMacro(vtkOpenGLHyperTreeGridMapper, vtkHyperTreeGridMapper);
+  void PrintSelf(ostream& os, vtkIndent indent) override;
+
+protected:
+  vtkOpenGLHyperTreeGridMapper();
+  virtual ~vtkOpenGLHyperTreeGridMapper() = default;
+
+private:
+  vtkOpenGLHyperTreeGridMapper(const vtkOpenGLHyperTreeGridMapper&) = delete;
+  void operator=(const vtkOpenGLHyperTreeGridMapper&) = delete;
+};
+
+#endif
diff --git a/Rendering/OpenGL2/vtkOpenGLPolyDataMapper.cxx b/Rendering/OpenGL2/vtkOpenGLPolyDataMapper.cxx
index d64ed19ad05..0e56e740b1b 100644
--- a/Rendering/OpenGL2/vtkOpenGLPolyDataMapper.cxx
+++ b/Rendering/OpenGL2/vtkOpenGLPolyDataMapper.cxx
@@ -3555,7 +3555,6 @@ void vtkOpenGLPolyDataMapper::ComputeBounds()
 //------------------------------------------------------------------------------
 void vtkOpenGLPolyDataMapper::UpdateBufferObjects(vtkRenderer* ren, vtkActor* act)
 {
-  std::cout << "UpdateBufferObjects" << std::endl;
   // Rebuild buffers if needed
   if (this->GetNeedToRebuildBufferObjects(ren, act))
   {
@@ -3781,7 +3780,6 @@ void vtkOpenGLPolyDataMapper::BuildBufferObjects(vtkRenderer* ren, vtkActor* act
       c = nullptr;
     }
   }
-  std::cout << "HaveCellScalars " << this->HaveCellScalars << std::endl;
 
   this->HaveCellNormals = false;
   // Do we have cell normals?
@@ -3819,7 +3817,6 @@ void vtkOpenGLPolyDataMapper::BuildBufferObjects(vtkRenderer* ren, vtkActor* act
   if (this->CellTextureBuildState != this->TempState)
   {
     this->CellTextureBuildState = this->TempState;
-    std::cout << "Building cell textures " << std::endl;
     this->BuildCellTextures(ren, act, prims, representation);
   }
 
@@ -4072,7 +4069,6 @@ void vtkOpenGLPolyDataMapper::AddCellIdsToSelectionPrimitives(vtkPolyData* poly,
     }
   };
 
-  std::cout << "arrayName " << arrayName << std::endl;
   if (arrayName)
   {
     // compute corresponding cell ids from selected id or value.
@@ -4093,7 +4089,6 @@ void vtkOpenGLPolyDataMapper::AddCellIdsToSelectionPrimitives(vtkPolyData* poly,
 void vtkOpenGLPolyDataMapper::BuildSelectionIBO(
   vtkPolyData* poly, std::vector<unsigned int> (&indices)[4], vtkIdType offset)
 {
-  std::cout << "BuildSelectionIBO " << std::endl;
   // We need to construct primitives based on a vtkSelection.
   // These primitives are filtered based on composite index and process index.
   for (int i = 0; i < 4; i++)
@@ -4208,7 +4203,6 @@ void vtkOpenGLPolyDataMapper::BuildSelectionIBO(
 void vtkOpenGLPolyDataMapper::BuildSelectionCache(
   const char* arrayName, bool selectingPoints, vtkPolyData* poly)
 {
-  std::cout << "BuildSelectionCache " << std::endl;
   if (arrayName &&
     (this->SelectionCacheForPoints != selectingPoints || this->SelectionCacheName != arrayName ||
       this->SelectionCacheTime < poly->GetMTime() || poly != this->SelectionPolyData))
@@ -4377,7 +4371,6 @@ void vtkOpenGLPolyDataMapper::PrintSelf(ostream& os, vtkIndent indent)
 void vtkOpenGLPolyDataMapper::ProcessSelectorPixelBuffers(
   vtkHardwareSelector* sel, std::vector<unsigned int>& pixeloffsets, vtkProp* prop)
 {
-  std::cout << "ProcessSelectorPixelBuffers " << std::endl;
   vtkPolyData* poly = this->CurrentInput;
 
   if (!this->PopulateSelectionSettings || !poly)
-- 
GitLab