Salome HOME
Addition of Bivariate noise representation to deal with 2D/3D uncertainties visualization
authorAnthony Geay <anthony.geay@edf.fr>
Thu, 30 Mar 2023 14:48:19 +0000 (16:48 +0200)
committerAnthony Geay <anthony.geay@edf.fr>
Thu, 30 Mar 2023 14:48:19 +0000 (16:48 +0200)
20 files changed:
src/Plugins/BivariateRepresentations/CMakeLists.txt [new file with mode: 0644]
src/Plugins/BivariateRepresentations/Plugin/CMakeLists.txt [new file with mode: 0644]
src/Plugins/BivariateRepresentations/Plugin/Representations/BivariateRepresentations.xml [new file with mode: 0644]
src/Plugins/BivariateRepresentations/Plugin/Representations/CMakeLists.txt [new file with mode: 0644]
src/Plugins/BivariateRepresentations/Plugin/Representations/vtk.module [new file with mode: 0644]
src/Plugins/BivariateRepresentations/Plugin/Representations/vtkBivariateNoiseMapper.cxx [new file with mode: 0644]
src/Plugins/BivariateRepresentations/Plugin/Representations/vtkBivariateNoiseMapper.h [new file with mode: 0644]
src/Plugins/BivariateRepresentations/Plugin/Representations/vtkBivariateNoiseRepresentation.cxx [new file with mode: 0644]
src/Plugins/BivariateRepresentations/Plugin/Representations/vtkBivariateNoiseRepresentation.h [new file with mode: 0644]
src/Plugins/BivariateRepresentations/Plugin/Testing/BivariateNoiseRepresentation.xml [new file with mode: 0644]
src/Plugins/BivariateRepresentations/Plugin/Testing/CMakeLists.txt [new file with mode: 0644]
src/Plugins/BivariateRepresentations/Plugin/Testing/Data/Baseline/BivariateNoise_A.png.sha512 [new file with mode: 0644]
src/Plugins/BivariateRepresentations/Plugin/Testing/Data/Baseline/BivariateNoise_B.png.sha512 [new file with mode: 0644]
src/Plugins/BivariateRepresentations/Plugin/Testing/Data/Baseline/BivariateNoise_C.png.sha512 [new file with mode: 0644]
src/Plugins/BivariateRepresentations/Plugin/Testing/Data/Baseline/BivariateNoise_D.png.sha512 [new file with mode: 0644]
src/Plugins/BivariateRepresentations/Plugin/paraview.plugin [new file with mode: 0644]
src/Plugins/BivariateRepresentations/Plugin/pqBivariateAnimationManager.cxx [new file with mode: 0644]
src/Plugins/BivariateRepresentations/Plugin/pqBivariateAnimationManager.h [new file with mode: 0644]
src/Plugins/BivariateRepresentations/README.md [new file with mode: 0644]
src/Plugins/CMakeLists.txt

diff --git a/src/Plugins/BivariateRepresentations/CMakeLists.txt b/src/Plugins/BivariateRepresentations/CMakeLists.txt
new file mode 100644 (file)
index 0000000..071d019
--- /dev/null
@@ -0,0 +1,39 @@
+cmake_minimum_required(VERSION 3.8)
+
+#project(BivariateRepresentations)
+set(PROJECT_NAME BivariateRepresentations)
+set(CMAKE_PROJECT_NAME BivariateRepresentations)
+find_package(ParaView REQUIRED)
+
+option(BUILD_SHARED_LIBS "Build shared libraries" ON)
+enable_testing()
+
+include(GNUInstallDirs)
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}")
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")
+set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")
+
+set("_paraview_plugin_default_${CMAKE_PROJECT_NAME}" ON)
+paraview_plugin_scan(
+  PLUGIN_FILES      "${CMAKE_CURRENT_SOURCE_DIR}/Plugin/paraview.plugin"
+  PROVIDES_PLUGINS  plugins
+  REQUIRES_MODULES  required_modules)
+
+foreach (module IN LISTS required_modules)
+  if (NOT TARGET "${module}")
+    message(#FATAL_ERROR
+      "Skipping example ${CMAKE_PROJECT_NAME}: Missing required module: "
+      "${module}")
+    return ()
+  endif ()
+endforeach ()
+
+paraview_plugin_build(
+  RUNTIME_DESTINATION "${CMAKE_INSTALL_BINDIR}"
+  LIBRARY_DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+  LIBRARY_SUBDIRECTORY "${PARAVIEW_PLUGIN_SUBDIR}"
+  PLUGINS ${plugins})
+
+# ????? rollback CMAKE_PROJECT_NAME
+set(PROJECT_NAME SalomePARAVIS)
+set(CMAKE_PROJECT_NAME SalomePARAVIS)
diff --git a/src/Plugins/BivariateRepresentations/Plugin/CMakeLists.txt b/src/Plugins/BivariateRepresentations/Plugin/CMakeLists.txt
new file mode 100644 (file)
index 0000000..f63635c
--- /dev/null
@@ -0,0 +1,36 @@
+if (PARAVIEW_USE_QT)
+  list(APPEND sources
+    pqBivariateAnimationManager.cxx
+    pqBivariateAnimationManager.h)
+
+  paraview_plugin_add_auto_start(
+    CLASS_NAME "pqBivariateAnimationManager"
+    STARTUP onStartup
+    SHUTDOWN onShutdown
+    INTERFACES autostart_interface
+    SOURCES autostart_sources)
+  list(APPEND interfaces
+    ${autostart_interface})
+  list(APPEND sources
+    ${autostart_sources})
+endif ()
+
+paraview_add_plugin(BivariateRepresentations
+  REQUIRED_ON_CLIENT
+  REQUIRED_ON_SERVER
+  VERSION "1.0"
+  UI_INTERFACES ${interfaces}
+  SOURCES ${sources}
+  MODULES BivariateRepresentations::vtkBivariateRepresentations
+  MODULE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/Representations/vtk.module"
+  XML_DOCUMENTATION OFF)
+ install(TARGETS BivariateRepresentations
+  RUNTIME DESTINATION lib/paraview
+  LIBRARY DESTINATION lib/paraview
+  ARCHIVE DESTINATION lib/paraview
+  )
+
+if (BUILD_TESTING)
+  add_subdirectory(Testing)
+endif()
diff --git a/src/Plugins/BivariateRepresentations/Plugin/Representations/BivariateRepresentations.xml b/src/Plugins/BivariateRepresentations/Plugin/Representations/BivariateRepresentations.xml
new file mode 100644 (file)
index 0000000..f194ef1
--- /dev/null
@@ -0,0 +1,194 @@
+<ServerManagerConfiguration>
+  <ProxyGroup name="representations">
+    <RepresentationProxy name="BivariateNoiseRepresentation"
+                         class="vtkBivariateNoiseRepresentation"
+                         processes="client|renderserver|dataserver"
+                         base_proxygroup="representations"
+                         base_proxyname="SurfaceRepresentation">
+      <Documentation>
+        This representation displays the values of the secondary array in the form of noise.
+      </Documentation>
+
+      <StringVectorProperty name="NoiseArray"
+                            command="SetInputArrayToProcess"
+                            number_of_elements="5"
+                            element_types="int int int int str"
+                            default_values="1 0 0 0 0">
+        <ArrayListDomain name="array_list"
+                         attribute_type="Scalars"
+                         input_domain_name="input_array_point_1">
+          <RequiredProperties>
+            <Property name="Input" function="Input"/>
+          </RequiredProperties>
+        </ArrayListDomain>
+        <Documentation>
+          This property specifies the name of the input array displayed with noise.
+        </Documentation>
+      </StringVectorProperty>
+
+      <DoubleVectorProperty name="Granularity"
+                            command="SetFrequency"
+                            number_of_elements="1"
+                            default_values="30.0">
+        <DoubleRangeDomain name="range" min="0.0" max="150.0"/>
+        <Documentation>
+          This property specifies a value for the granularity (frequency) of the noise.
+        </Documentation>
+      </DoubleVectorProperty>
+
+      <DoubleVectorProperty name="Amplitude"
+                            command="SetAmplitude"
+                            number_of_elements="1"
+                            default_values="0.5">
+        <DoubleRangeDomain name="range" min="0.0" max="1.0"/>
+        <Documentation>
+          This property specifies a value for the amplitude of the noise.
+        </Documentation>
+      </DoubleVectorProperty>
+
+      <DoubleVectorProperty name="AnimationSpeedFactor"
+                            command="SetSpeed"
+                            number_of_elements="1"
+                            default_values="1.0">
+        <DoubleRangeDomain name="range" min="0.0" max="3.0"/>
+        <Documentation>
+          This property specifies a factor modifying the speed animation of the noise animation.
+        </Documentation>
+      </DoubleVectorProperty>
+
+      <IntVectorProperty name="NbOfOctaves"
+                         command="SetNbOfOctaves"
+                         number_of_elements="1"
+                         default_values="3">
+        <IntRangeDomain name="range" min="0" max="5"/>
+        <Documentation>
+          This property specifies the number of octaves of noise (overlaping layers of noise).
+        </Documentation>
+      </IntVectorProperty>
+    <!-- End of BivariateNoiseRepresentation -->
+    </RepresentationProxy>
+
+    <Extension name="GeometryRepresentation">
+      <Documentation>
+        Extends standard GeometryRepresentation by adding
+        BivariateNoiseRepresentation as a new type of representation.
+      </Documentation>
+
+      <RepresentationType subproxy="BivariateNoiseRepresentation"
+                          text="Bivariate Noise Surface"
+                          subtype="Surface"/>
+
+      <SubProxy>
+        <Proxy name="BivariateNoiseRepresentation"
+               proxygroup="representations"
+               proxyname="BivariateNoiseRepresentation">
+        </Proxy>
+
+        <ShareProperties subproxy="SurfaceRepresentation">
+          <Exception name="Input"/>
+          <Exception name="Visibility"/>
+          <Exception name="Representation"/>
+        </ShareProperties>
+
+        <ExposedProperties>
+          <PropertyGroup label="Bivariate representation">
+            <Property name="NoiseArray"/>
+            <Property name="Granularity"/>
+            <Property name="Amplitude"/>
+            <Property name="AnimationSpeedFactor"/>
+            <Property name="NbOfOctaves"/>
+            <Hints>
+              <PropertyWidgetDecorator type="GenericDecorator"
+                                       mode="visibility"
+                                       property="Representation"
+                                       value="Bivariate Noise Surface"/>
+            </Hints>
+          </PropertyGroup>
+        </ExposedProperties>
+      </SubProxy>
+    <!-- End of GeometryRepresentation Extension -->
+    </Extension>
+
+    <Extension name="UnstructuredGridRepresentation">
+      <Documentation>
+        Extends standard UnstructuredGridRepresentation by adding
+        BivariateNoiseRepresentation as a new type of representation.
+      </Documentation>
+
+      <RepresentationType subproxy="BivariateNoiseRepresentation"
+                          text="Bivariate Noise Surface"
+                          subtype="Surface"/>
+
+      <SubProxy>
+        <Proxy name="BivariateNoiseRepresentation"
+               proxygroup="representations"
+               proxyname="BivariateNoiseRepresentation">
+        </Proxy>
+
+        <ShareProperties subproxy="SurfaceRepresentation">
+          <Exception name="Input"/>
+          <Exception name="Visibility"/>
+          <Exception name="Representation"/>
+        </ShareProperties>
+
+        <ExposedProperties>
+          <PropertyGroup label="Bivariate representation">
+            <Property name="NoiseArray"/>
+            <Property name="Granularity"/>
+            <Property name="Amplitude"/>
+            <Property name="AnimationSpeedFactor"/>
+            <Property name="NbOfOctaves"/>
+            <Hints>
+              <PropertyWidgetDecorator type="GenericDecorator"
+                                       mode="visibility"
+                                       property="Representation"
+                                       value="Bivariate Noise Surface"/>
+            </Hints>
+          </PropertyGroup>
+        </ExposedProperties>
+      </SubProxy>
+    <!-- End of UnstructuredGridRepresentation Extension -->
+    </Extension>
+
+    <Extension name="UniformGridRepresentation">
+      <Documentation>
+        Extends standard UniformGridRepresentation by adding
+        BivariateNoiseRepresentation as a new type of representation.
+      </Documentation>
+
+      <RepresentationType subproxy="BivariateNoiseRepresentation"
+                          text="Bivariate Noise Surface"
+                          subtype="Surface"/>
+
+      <SubProxy>
+        <Proxy name="BivariateNoiseRepresentation"
+               proxygroup="representations"
+               proxyname="BivariateNoiseRepresentation">
+        </Proxy>
+
+        <ShareProperties subproxy="SurfaceRepresentation">
+          <Exception name="Input"/>
+          <Exception name="Visibility"/>
+          <Exception name="Representation"/>
+        </ShareProperties>
+
+        <ExposedProperties>
+          <PropertyGroup label="Bivariate representation">
+            <Property name="NoiseArray"/>
+            <Property name="Granularity"/>
+            <Property name="Amplitude"/>
+            <Property name="AnimationSpeedFactor"/>
+            <Property name="NbOfOctaves"/>
+            <Hints>
+              <PropertyWidgetDecorator type="GenericDecorator"
+                                       mode="visibility"
+                                       property="Representation"
+                                       value="Bivariate Noise Surface"/>
+            </Hints>
+          </PropertyGroup>
+        </ExposedProperties>
+      </SubProxy>
+    <!-- End of UniformGridRepresentation Extension -->
+    </Extension>
+  </ProxyGroup>
+</ServerManagerConfiguration>
diff --git a/src/Plugins/BivariateRepresentations/Plugin/Representations/CMakeLists.txt b/src/Plugins/BivariateRepresentations/Plugin/Representations/CMakeLists.txt
new file mode 100644 (file)
index 0000000..c72794d
--- /dev/null
@@ -0,0 +1,10 @@
+set(classes
+  vtkBivariateNoiseMapper
+  vtkBivariateNoiseRepresentation)
+
+vtk_module_add_module(BivariateRepresentations::vtkBivariateRepresentations
+  FORCE_STATIC
+  CLASSES ${classes})
+
+paraview_add_server_manager_xmls(
+  XMLS  BivariateRepresentations.xml)
diff --git a/src/Plugins/BivariateRepresentations/Plugin/Representations/vtk.module b/src/Plugins/BivariateRepresentations/Plugin/Representations/vtk.module
new file mode 100644 (file)
index 0000000..ae6cf30
--- /dev/null
@@ -0,0 +1,7 @@
+NAME
+  BivariateRepresentations::vtkBivariateRepresentations
+DEPENDS
+  ParaView::RemotingViews
+  VTK::RenderingOpenGL2
+PRIVATE_DEPENDS
+  VTK::CommonCore
diff --git a/src/Plugins/BivariateRepresentations/Plugin/Representations/vtkBivariateNoiseMapper.cxx b/src/Plugins/BivariateRepresentations/Plugin/Representations/vtkBivariateNoiseMapper.cxx
new file mode 100644 (file)
index 0000000..3cb6925
--- /dev/null
@@ -0,0 +1,419 @@
+/*=========================================================================
+
+  Program:   ParaView
+  Module:    vtkBivariateNoiseMapper.cxx
+
+  Copyright (c) Kitware, Inc.
+  All rights reserved.
+  See Copyright.txt or http://www.paraview.org/HTML/Copyright.html 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.
+
+=========================================================================*/
+// vtk_glew.h should be included before vtkCompositeMapperHelper2 for OpenGL enums.
+// This include can be removed in ParaView 5.12.
+#include "vtk_glew.h"
+
+#include "vtkBivariateNoiseMapper.h"
+#include "vtkCompositeMapperHelper2.h"
+#include "vtkFloatArray.h"
+#include "vtkObjectFactory.h"
+#include "vtkOpenGLUniforms.h"
+#include "vtkOpenGLVertexBufferObjectGroup.h"
+#include "vtkPointData.h"
+#include "vtkPolyData.h"
+#include "vtkRenderer.h"
+#include "vtkShader.h"
+#include "vtkShaderProgram.h"
+#include "vtkShaderProperty.h"
+
+#include <chrono>
+
+//----------------------------------------------------------------------------
+struct vtkBivariateNoiseMapper::vtkInternals
+{
+  double Frequency = 30.0;
+  double Amplitude = 0.5;
+  double Speed = 1.0;
+  int NbOfOctaves = 3;
+  long StartTime = 0;
+  bool Initialized = false;
+};
+
+//----------------------------------------------------------------------------
+/**
+ * The vtkBivariateNoiseMapperHelper inheritate indirectly from vtkOpenGLPolydataMapper
+ * and contains most of the rendering code specific to the vtkBivariateNoiseMapper.
+ */
+class vtkBivariateNoiseMapperHelper : public vtkCompositeMapperHelper2
+{
+public:
+  static vtkBivariateNoiseMapperHelper* New();
+  vtkTypeMacro(vtkBivariateNoiseMapperHelper, vtkCompositeMapperHelper2);
+
+protected:
+  vtkBivariateNoiseMapperHelper() = default;
+  ~vtkBivariateNoiseMapperHelper() override = default;
+
+  /**
+   * Contain most of the shader replacements specific to this mapper.
+   * Define the noise function and use it to generate the output of the fragment shader.
+   */
+  void ReplaceShaderColor(
+    std::map<vtkShader::Type, vtkShader*> shaders, vtkRenderer* ren, vtkActor* act) override;
+
+  /**
+   * Pass and interpolate vertex positions (in model coordinates)
+   * from the vertex shader to the fragment shader.
+   */
+  void ReplaceShaderPositionVC(
+    std::map<vtkShader::Type, vtkShader*> shaders, vtkRenderer* ren, vtkActor* actor) override;
+
+  /**
+   * Define the custom uniforms in the fragment shader (frequency, amplitude, time).
+   */
+  void ReplaceShaderCustomUniforms(
+    std::map<vtkShader::Type, vtkShader*> shaders, vtkActor* actor) override;
+
+  /**
+   * Set the custom uniforms values in the fragment shader.
+   */
+  void SetCustomUniforms(vtkOpenGLHelper& cellBO, vtkActor* actor) override;
+
+  /**
+   * Pass the noise array on the OpenGL side as a VBO.
+   */
+  void AppendOneBufferObject(vtkRenderer* ren, vtkActor* act, vtkCompositeMapperHelperData* hdata,
+    vtkIdType& flat_index, std::vector<unsigned char>& colors, std::vector<float>& norms) override;
+
+private:
+  vtkBivariateNoiseMapperHelper(const vtkBivariateNoiseMapperHelper&) = delete;
+  void operator=(const vtkBivariateNoiseMapperHelper&) = delete;
+};
+
+//----------------------------------------------------------------------------
+vtkStandardNewMacro(vtkBivariateNoiseMapperHelper);
+
+//----------------------------------------------------------------------------
+void vtkBivariateNoiseMapperHelper::ReplaceShaderColor(
+  std::map<vtkShader::Type, vtkShader*> shaders, vtkRenderer* ren, vtkActor* act)
+{
+  // InterpolateScalarsBeforeMapping: noise effect is applied during color lookup in the FS.
+  // ColorCoordinates: we need the first array values.
+  if (this->InterpolateScalarsBeforeMapping && this->ColorCoordinates && !this->DrawingVertices)
+  {
+    // The bivariate data correspond to the second array to show
+    // in the form of Perlin noise intensity.
+    std::string colorDecVS =
+      R"(
+in float bivariateData;
+out float vertexBivariateDataVSOut;
+)";
+
+    // The bivariate data should be interpolated between VS and FS.
+    // We interpolate the scalars before mapping the colors in the FS.
+    std::string colorImplVS =
+      R"(
+  vertexBivariateDataVSOut = bivariateData;
+  )";
+
+    // Here we define our functions (Perlin 4D noise + utilities).
+    std::string colorDecFS =
+      R"(
+vec4 random4D(in vec4 inVec)
+{
+  // Dot products of the coordinates with arbitrary vectors
+  float dot1 = dot(inVec, vec4(152.235, 478.267, -574.241, 342.365));
+  float dot2 = dot(inVec, vec4(328.438, 575.981, 124.254, -132.43));
+  float dot3 = dot(inVec, vec4(-28.438, -175.981, 287.399, 45.201));
+  float dot4 = dot(inVec, vec4(522.378, -2.358, 355.247, -123.321));
+
+  // Multiply sin with big number, keep the fractionnal part: pseudo-random vector
+  // *2 - 1 : ensure negative coordinates are possible
+  return fract(sin(vec4(dot1, dot2, dot3, dot4)) * 458724.) * 2. - vec4(1., 1., 1., 1.);
+}
+
+// Use quintic Hermite interpolation for smoother results than the classic
+// smoothstep function (that uses cubic Hermite interpolation)
+float quinticSmooth(in float t)
+{
+  // No clamp needed like smoothstep as we are garanteed
+  // to have t between 0. and 1. here
+  return t * t * t *(t * (t * 6. -15.) + 10.);
+}
+
+float noise(in vec4 inVec)
+{
+  // Interger and fractional parts
+  vec4 i_inVec = floor(inVec); // "4D tile" where inVec belongs
+  vec4 f_inVec = fract(inVec); // Where in the tile (between 0. and 1.)
+
+  // Random values at corners of the 4D tile where inVec belongs
+  float val0000 = dot(random4D(i_inVec + vec4(0., 0., 0., 0.)), f_inVec - vec4(0., 0., 0., 0.));
+  float val0001 = dot(random4D(i_inVec + vec4(0., 0., 0., 1.)), f_inVec - vec4(0., 0., 0., 1.));
+  float val0010 = dot(random4D(i_inVec + vec4(0., 0., 1., 0.)), f_inVec - vec4(0., 0., 1., 0.));
+  float val0011 = dot(random4D(i_inVec + vec4(0., 0., 1., 1.)), f_inVec - vec4(0., 0., 1., 1.));
+  float val0100 = dot(random4D(i_inVec + vec4(0., 1., 0., 0.)), f_inVec - vec4(0., 1., 0., 0.));
+  float val0101 = dot(random4D(i_inVec + vec4(0., 1., 0., 1.)), f_inVec - vec4(0., 1., 0., 1.));
+  float val0110 = dot(random4D(i_inVec + vec4(0., 1., 1., 0.)), f_inVec - vec4(0., 1., 1., 0.));
+  float val0111 = dot(random4D(i_inVec + vec4(0., 1., 1., 1.)), f_inVec - vec4(0., 1., 1., 1.));
+  float val1000 = dot(random4D(i_inVec + vec4(1., 0., 0., 0.)), f_inVec - vec4(1., 0., 0., 0.));
+  float val1001 = dot(random4D(i_inVec + vec4(1., 0., 0., 1.)), f_inVec - vec4(1., 0., 0., 1.));
+  float val1010 = dot(random4D(i_inVec + vec4(1., 0., 1., 0.)), f_inVec - vec4(1., 0., 1., 0.));
+  float val1011 = dot(random4D(i_inVec + vec4(1., 0., 1., 1.)), f_inVec - vec4(1., 0., 1., 1.));
+  float val1100 = dot(random4D(i_inVec + vec4(1., 1., 0., 0.)), f_inVec - vec4(1., 1., 0., 0.));
+  float val1101 = dot(random4D(i_inVec + vec4(1., 1., 0., 1.)), f_inVec - vec4(1., 1., 0., 1.));
+  float val1110 = dot(random4D(i_inVec + vec4(1., 1., 1., 0.)), f_inVec - vec4(1., 1., 1., 0.));
+  float val1111 = dot(random4D(i_inVec + vec4(1., 1., 1., 1.)), f_inVec - vec4(1., 1., 1., 1.));
+
+  // Smooth interpolation along each axis of the 4D tile
+  float x_smooth = quinticSmooth(f_inVec.x);
+  float y_smooth = quinticSmooth(f_inVec.y);
+  float z_smooth = quinticSmooth(f_inVec.z);
+  float w_smooth = quinticSmooth(f_inVec.w);
+
+  // Quadrilinear interpolation
+  float x_inter1 = mix(val0000, val1000, x_smooth);
+  float x_inter2 = mix(val0100, val1100, x_smooth);
+  float x_inter3 = mix(val0010, val1010, x_smooth);
+  float x_inter4 = mix(val0110, val1110, x_smooth);
+  float x_inter5 = mix(val0001, val1001, x_smooth);
+  float x_inter6 = mix(val0101, val1101, x_smooth);
+  float x_inter7 = mix(val0011, val1011, x_smooth);
+  float x_inter8 = mix(val0111, val1111, x_smooth);
+
+  float y_inter1 = mix(x_inter1, x_inter2, y_smooth);
+  float y_inter2 = mix(x_inter3, x_inter4, y_smooth);
+  float y_inter3 = mix(x_inter5, x_inter6, y_smooth);
+  float y_inter4 = mix(x_inter7, x_inter8, y_smooth);
+
+  float z_inter1 = mix(y_inter1, y_inter2, z_smooth);
+  float z_inter2 = mix(y_inter3, y_inter4, z_smooth);
+
+  return mix(z_inter1, z_inter2, w_smooth);
+}
+
+// Fractal noise
+// Add "layers" of noise by iterating over octaves.
+float fNoise (in vec4 inVec, in int nbOfOctaves)
+{
+  float result = 0.;
+  float freqMultiplier = 1.;
+  float ampMultiplier = 1.;
+
+  // Loop over each octave. At each step,
+  // double the frequency and divide by 2 the amplitude.
+  for (int i = 0; i < nbOfOctaves; i++)
+  {
+    result += ampMultiplier * noise(inVec * freqMultiplier);
+    freqMultiplier *= 2.;
+    ampMultiplier *= 0.5;
+  }
+  return result;
+}
+
+in float vertexBivariateDataVSOut;
+)";
+
+    // Here we apply the value of the 4D Perlin noise (depending on the noise array)
+    // on the value of 2D texture coordinates (tcoordVCVSOutput.s corresponds to the 1st data
+    // array with values clamped between 0.0 and 1.0, tcoordVCVSOutput.t is always equal to 0).
+    // This ends up oscillating over the color texture (1D).
+    // Bigger is the noise array value, bigger is the amplitude.
+    std::string colorImplFS =
+      R"(
+  // Input vector: 3D coordinates + time.
+  vec4 inVec = vec4(vertexMCVSOutput.xyz * frequency, currentTime * speed);
+
+  // Compute and apply the noise value to modify the color texture coordinates.
+  float noise = fNoise(inVec, nbOfOctaves);
+  vec2 _texCoord = tcoordVCVSOutput.st + vec2(noise, 0.) * amplitude * vertexBivariateDataVSOut;
+  )";
+
+    vtkShaderProgram::Substitute(
+      shaders[vtkShader::Vertex], "//VTK::Color::Dec", colorDecVS + "\n//VTK::Color::Dec\n");
+    vtkShaderProgram::Substitute(
+      shaders[vtkShader::Vertex], "//VTK::Color::Impl", colorImplVS + "\n//VTK::Color::Impl\n");
+    vtkShaderProgram::Substitute(
+      shaders[vtkShader::Fragment], "//VTK::Color::Dec", colorDecFS + "\n//VTK::Color::Dec\n");
+    vtkShaderProgram::Substitute(
+      shaders[vtkShader::Fragment], "//VTK::Color::Impl", colorImplFS + "\n//VTK::Color::Impl\n");
+
+    this->Superclass::ReplaceShaderColor(shaders, ren, act);
+
+    // Now we need to override the texColor value (after the replacements defined in
+    // vtkOpenGLPolyDataMapper) in order to use our custom _texCoord value.
+    vtkShaderProgram::Substitute(shaders[vtkShader::Fragment],
+      "vec4 texColor = texture(colortexture, tcoordVCVSOutput.st);",
+      "vec4 texColor = texture(colortexture, _texCoord);");
+  }
+  else
+  {
+    // Just call superclass
+    this->Superclass::ReplaceShaderColor(shaders, ren, act);
+  }
+}
+
+//----------------------------------------------------------------------------
+void vtkBivariateNoiseMapperHelper::ReplaceShaderPositionVC(
+  std::map<vtkShader::Type, vtkShader*> shaders, vtkRenderer* ren, vtkActor* actor)
+{
+  // We need to interpolate the vertex positions (in model coordinate)
+  // between the vertex shader and the fragment shader, because the Perlin
+  // noise function take it as a parameter.
+  vtkShaderProgram::Substitute(shaders[vtkShader::Vertex], "//VTK::PositionVC::Dec",
+    R"(
+//VTK::PositionVC::Dec
+out vec4 vertexMCVSOutput;
+)");
+
+  vtkShaderProgram::Substitute(shaders[vtkShader::Vertex], "//VTK::PositionVC::Impl",
+    R"(
+  //VTK::PositionVC::Impl
+  vertexMCVSOutput = vertexMC;
+  )");
+
+  // Fragment shader substitutions
+  vtkShaderProgram::Substitute(shaders[vtkShader::Fragment], "//VTK::PositionVC::Dec",
+    R"(
+//VTK::PositionVC::Dec
+in vec4 vertexMCVSOutput;
+)");
+
+  this->Superclass::ReplaceShaderPositionVC(shaders, ren, actor);
+}
+
+//----------------------------------------------------------------------------
+void vtkBivariateNoiseMapperHelper::ReplaceShaderCustomUniforms(
+  std::map<vtkShader::Type, vtkShader*> shaders, vtkActor* actor)
+{
+  vtkShaderProgram::Substitute(shaders[vtkShader::Fragment], "//VTK::CustomUniforms::Dec",
+    R"(
+//VTK::CustomUniforms::Dec
+uniform float frequency = 10.;
+uniform float amplitude = 0.5;
+uniform float speed = 1.;
+uniform int nbOfOctaves = 3;
+uniform float currentTime = 0.;
+)");
+
+  this->Superclass::ReplaceShaderCustomUniforms(shaders, actor);
+}
+
+//----------------------------------------------------------------------------
+void vtkBivariateNoiseMapperHelper::SetCustomUniforms(vtkOpenGLHelper& cellBO, vtkActor* actor)
+{
+  this->Superclass::SetCustomUniforms(cellBO, actor);
+  vtkBivariateNoiseMapper* parent = vtkBivariateNoiseMapper::SafeDownCast(this->Parent);
+  cellBO.Program->SetUniformf("frequency", parent->Internals->Frequency);
+  cellBO.Program->SetUniformf("amplitude", parent->Internals->Amplitude);
+  cellBO.Program->SetUniformf("speed", parent->Internals->Speed);
+  cellBO.Program->SetUniformi("nbOfOctaves", parent->Internals->NbOfOctaves);
+  auto time =
+    (std::chrono::steady_clock::now().time_since_epoch().count() - parent->Internals->StartTime) *
+    0.0000000006; // Value defined empirically for suitable default speed
+  cellBO.Program->SetUniformf("currentTime", time);
+}
+
+//------------------------------------------------------------------------------
+void vtkBivariateNoiseMapperHelper::AppendOneBufferObject(vtkRenderer* ren, vtkActor* act,
+  vtkCompositeMapperHelperData* hdata, vtkIdType& voffset, std::vector<unsigned char>& newColors,
+  std::vector<float>& newNorms)
+{
+  vtkPolyData* poly = hdata->Data;
+  vtkDataArray* array = this->GetInputArrayToProcess(1, poly); // Noise array
+  if (array && array->GetNumberOfComponents() == 1)
+  {
+    vtkNew<vtkFloatArray> floatArray;
+    floatArray->DeepCopy(array);
+    this->VBOs->AppendDataArray("bivariateData", floatArray, VTK_FLOAT);
+  }
+
+  this->Superclass::AppendOneBufferObject(ren, act, hdata, voffset, newColors, newNorms);
+}
+
+//----------------------------------------------------------------------------
+vtkStandardNewMacro(vtkBivariateNoiseMapper);
+
+//----------------------------------------------------------------------------
+vtkBivariateNoiseMapper::vtkBivariateNoiseMapper()
+  : Internals(new vtkBivariateNoiseMapper::vtkInternals())
+{
+}
+
+//----------------------------------------------------------------------------
+vtkBivariateNoiseMapper::~vtkBivariateNoiseMapper() = default;
+
+//----------------------------------------------------------------------------
+void vtkBivariateNoiseMapper::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os, indent);
+  os << indent << "Frequency: " << this->Internals->Frequency << endl;
+  os << indent << "Amplitude: " << this->Internals->Amplitude << endl;
+  os << indent << "Speed: " << this->Internals->Speed << endl;
+  os << indent << "Nb of octaves: " << this->Internals->NbOfOctaves << endl;
+}
+
+//----------------------------------------------------------------------------
+vtkCompositeMapperHelper2* vtkBivariateNoiseMapper::CreateHelper()
+{
+  return vtkBivariateNoiseMapperHelper::New();
+}
+
+//----------------------------------------------------------------------------
+void vtkBivariateNoiseMapper::CopyMapperValuesToHelper(vtkCompositeMapperHelper2* helper)
+{
+  this->Superclass::CopyMapperValuesToHelper(helper);
+  helper->SetInputArrayToProcess(1, this->GetInputArrayInformation(1)); // Noise array
+}
+
+//----------------------------------------------------------------------------
+void vtkBivariateNoiseMapper::SetFrequency(double frequency)
+{
+  this->Internals->Frequency = frequency;
+  this->Modified();
+}
+
+//----------------------------------------------------------------------------
+void vtkBivariateNoiseMapper::SetAmplitude(double amplitude)
+{
+  this->Internals->Amplitude = amplitude;
+  this->Modified();
+}
+
+//----------------------------------------------------------------------------
+void vtkBivariateNoiseMapper::SetSpeed(double speed)
+{
+  this->Internals->Speed = speed;
+  this->Modified();
+}
+
+//----------------------------------------------------------------------------
+void vtkBivariateNoiseMapper::SetNbOfOctaves(int nbOfOctaves)
+{
+  this->Internals->NbOfOctaves = nbOfOctaves;
+  this->Modified();
+}
+
+//----------------------------------------------------------------------------
+void vtkBivariateNoiseMapper::Render(vtkRenderer* ren, vtkActor* act)
+{
+  if (!this->Internals->Initialized)
+  {
+    this->Initialize();
+  }
+  this->Superclass::Render(ren, act);
+}
+
+//----------------------------------------------------------------------------
+void vtkBivariateNoiseMapper::Initialize()
+{
+  if (!this->Internals->Initialized)
+  {
+    this->Internals->StartTime = std::chrono::steady_clock::now().time_since_epoch().count();
+    this->Internals->Initialized = true;
+    this->Modified();
+  }
+}
diff --git a/src/Plugins/BivariateRepresentations/Plugin/Representations/vtkBivariateNoiseMapper.h b/src/Plugins/BivariateRepresentations/Plugin/Representations/vtkBivariateNoiseMapper.h
new file mode 100644 (file)
index 0000000..f31b3dc
--- /dev/null
@@ -0,0 +1,140 @@
+/*=========================================================================
+
+  Program:   ParaView
+  Module:    vtkBivariateNoiseMapper.h
+
+  Copyright (c) Kitware, Inc.
+  All rights reserved.
+  See Copyright.txt or http://www.paraview.org/HTML/Copyright.html 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 vtkBivariateNoiseMapper
+ * @brief Mapper to visualize bivariate data with noise
+ *
+ * The vtkBivariateNoiseMapper allow to visualize bivariate data with Perlin noise.
+ * A second array can be passed to this mapper. The values of this array will be used
+ * to control the noise intensity: the bigger the values are, the bigger the intensity
+ * of the noise is (values are clamped between 0 and 1; a value of 0 corresponds to no
+ * noise at all.)
+ *
+ * The user can control the noise with 4 parameters:
+ * - the Frequency parameter controls the number of cells (tiles) used to
+ *   generate the noise,
+ * - the Amplitude parameter controls how much the values of the noise array
+ *   affect the amplitude of the noise,
+ * - the Speed parameter controls the speed of the noise animation,
+ * - the NbOctaves controls the number of layers of noise (octaves) to generate.
+ *   Please note that adding octaves leads to a performance cost.
+ *
+ * Please note that the vtkBivariateNoiseMapper only works with point data.
+ * Furthermore:
+ * - you must always define a 1st array for coloring,
+ * - the mapper only accept scalar values for the noise array,
+ * - the InterpolateScalarsBeforeMapping option should be set to true.
+ * If these requirement are not fullfiled, the vtkBivariateNoiseMapper
+ * acts as the standard vtkOpenGLPolyDataMapper.
+ *
+ * This mapper shader implementation is based on concepts and ideas
+ * comming from the following sources:
+ * - https://en.wikipedia.org/wiki/Perlin_noise
+ * - https://thebookofshaders.com/11/
+ * - https://thebookofshaders.com/13/
+ * - https://x-engineer.org/bilinear-interpolation/
+ *
+ * @sa vtkOpenGLPolyDataMapper vtkBivariateNoiseRepresentation
+ */
+
+#ifndef vtkBivariateNoiseMapper_h
+#define vtkBivariateNoiseMapper_h
+
+#include "vtkBivariateRepresentationsModule.h" // for export macro
+#include "vtkCompositePolyDataMapper2.h"
+
+#include <memory> // for unique_ptr
+
+class VTKBIVARIATEREPRESENTATIONS_EXPORT vtkBivariateNoiseMapper
+  : public vtkCompositePolyDataMapper2
+{
+public:
+  static vtkBivariateNoiseMapper* New();
+  vtkTypeMacro(vtkBivariateNoiseMapper, vtkCompositePolyDataMapper2);
+  void PrintSelf(ostream& os, vtkIndent indent) override;
+
+  /**
+   * Set the frequency of the noise.
+   * The frequency correspond to the "number of subdivisions" of the 4D
+   * grid from which the first layer of noise is generated (can be a floating value).
+   * Default is 30.0.
+   */
+  void SetFrequency(double frequency);
+
+  /**
+   * Set the final amplitude of the noise.
+   * This acts as a multiplier controlling the impact of the noise
+   * value on the color of the first data array.
+   * Default is 1.0.
+   */
+  void SetAmplitude(double amplitude);
+
+  /**
+   * Set the speed of the nois animation.
+   * This is a multiplier applied to the original speed.
+   * Default is 1.0.
+   */
+  void SetSpeed(double speed);
+
+  /**
+   * Set the number of layers of noise.
+   * This controls the number of octaves (layers) of noise added to the resulting noise.
+   * For each extra layer, the noise is recomputed using a frequency multiplied by two,
+   * and an amplitude divided by 2 comparatively to the previous iteration.
+   * Implies a performance cost (noise is recomputed for each layer).
+   * Default is 3.0.
+   */
+  void SetNbOfOctaves(int nbOctaves);
+
+  /**
+   * Initialize the mapper if needed then render.
+   */
+  void Render(vtkRenderer* ren, vtkActor* act) override;
+
+protected:
+  vtkBivariateNoiseMapper();
+  ~vtkBivariateNoiseMapper() override;
+
+  /**
+   * Starts the internal timer for noise animation.
+   * Done automatically in the first Render() call.
+   */
+  void Initialize();
+
+  /**
+   * Override the creation of the helper to create a dedicated mapper helper.
+   * This helper inheritate indirectly from vtkOpenGLPolydataMapper and contains
+   * most of the rendering code specific to the vtkBivariateNoiseMapper.
+   */
+  vtkCompositeMapperHelper2* CreateHelper() override;
+
+  /**
+   * Overriden to pass the noise array to the helper.
+   * The noise array should be passed to this mapper through the
+   * SetInputArrayToProcess method.
+   */
+  void CopyMapperValuesToHelper(vtkCompositeMapperHelper2* helper) override;
+
+private:
+  vtkBivariateNoiseMapper(const vtkBivariateNoiseMapper&) = delete;
+  void operator=(const vtkBivariateNoiseMapper&) = delete;
+
+  struct vtkInternals;
+  std::unique_ptr<vtkInternals> Internals;
+
+  friend class vtkBivariateNoiseMapperHelper;
+};
+
+#endif
diff --git a/src/Plugins/BivariateRepresentations/Plugin/Representations/vtkBivariateNoiseRepresentation.cxx b/src/Plugins/BivariateRepresentations/Plugin/Representations/vtkBivariateNoiseRepresentation.cxx
new file mode 100644 (file)
index 0000000..5ffde79
--- /dev/null
@@ -0,0 +1,91 @@
+/*=========================================================================
+
+  Program:   ParaView
+  Module:    vtkBivariateNoiseRepresentation.cxx
+
+  Copyright (c) Kitware, Inc.
+  All rights reserved.
+  See Copyright.txt or http://www.paraview.org/HTML/Copyright.html 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 "vtkBivariateNoiseRepresentation.h"
+
+#include "vtkBivariateNoiseMapper.h"
+#include "vtkDataObject.h"
+#include "vtkObjectFactory.h"
+
+vtkStandardNewMacro(vtkBivariateNoiseRepresentation);
+//----------------------------------------------------------------------------
+vtkBivariateNoiseRepresentation::vtkBivariateNoiseRepresentation()
+{
+  // Replace the mappers created by the superclass.
+  this->Mapper->Delete();
+  this->LODMapper->Delete();
+
+  this->Mapper = vtkBivariateNoiseMapper::New();
+  this->LODMapper = vtkBivariateNoiseMapper::New();
+
+  // Since we replaced the mappers, we need to call SetupDefaults() to ensure
+  // the pipelines are setup correctly.
+  this->SetupDefaults();
+}
+
+//----------------------------------------------------------------------------
+vtkBivariateNoiseRepresentation::~vtkBivariateNoiseRepresentation() = default;
+
+//----------------------------------------------------------------------------
+void vtkBivariateNoiseRepresentation::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os, indent);
+}
+
+//----------------------------------------------------------------------------
+void vtkBivariateNoiseRepresentation::SetInputArrayToProcess(
+  int idx, int port, int connection, int fieldAssociation, const char* attributeTypeorName)
+{
+  if (idx == 1 && fieldAssociation == vtkDataObject::FieldAssociations::FIELD_ASSOCIATION_POINTS)
+  {
+    // Pass the noise array to the mapper (idx == 1)
+    this->Mapper->SetInputArrayToProcess(
+      1, port, connection, fieldAssociation, attributeTypeorName);
+    this->LODMapper->SetInputArrayToProcess(
+      1, port, connection, fieldAssociation, attributeTypeorName);
+  }
+  else
+  {
+    this->Superclass::SetInputArrayToProcess(
+      idx, port, connection, fieldAssociation, attributeTypeorName);
+  }
+}
+
+//----------------------------------------------------------------------------
+void vtkBivariateNoiseRepresentation::SetFrequency(double frequency)
+{
+  vtkBivariateNoiseMapper::SafeDownCast(this->Mapper)->SetFrequency(frequency);
+  vtkBivariateNoiseMapper::SafeDownCast(this->LODMapper)->SetFrequency(frequency);
+}
+
+//----------------------------------------------------------------------------
+void vtkBivariateNoiseRepresentation::SetAmplitude(double amplitude)
+{
+  vtkBivariateNoiseMapper::SafeDownCast(this->Mapper)->SetAmplitude(amplitude);
+  vtkBivariateNoiseMapper::SafeDownCast(this->LODMapper)->SetAmplitude(amplitude);
+}
+
+//----------------------------------------------------------------------------
+void vtkBivariateNoiseRepresentation::SetSpeed(double speed)
+{
+  vtkBivariateNoiseMapper::SafeDownCast(this->Mapper)->SetSpeed(speed);
+  vtkBivariateNoiseMapper::SafeDownCast(this->LODMapper)->SetSpeed(speed);
+}
+
+//----------------------------------------------------------------------------
+void vtkBivariateNoiseRepresentation::SetNbOfOctaves(int nbOctaves)
+{
+  vtkBivariateNoiseMapper::SafeDownCast(this->Mapper)->SetNbOfOctaves(nbOctaves);
+  vtkBivariateNoiseMapper::SafeDownCast(this->LODMapper)->SetNbOfOctaves(nbOctaves);
+}
diff --git a/src/Plugins/BivariateRepresentations/Plugin/Representations/vtkBivariateNoiseRepresentation.h b/src/Plugins/BivariateRepresentations/Plugin/Representations/vtkBivariateNoiseRepresentation.h
new file mode 100644 (file)
index 0000000..9178ccb
--- /dev/null
@@ -0,0 +1,65 @@
+/*=========================================================================
+
+  Program:   ParaView
+  Module:    vtkBivariateNoiseRepresentation.h
+
+  Copyright (c) Kitware, Inc.
+  All rights reserved.
+  See Copyright.txt or http://www.paraview.org/HTML/Copyright.html 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 vtkBivariateNoiseRepresentation
+ * @brief Representation to visualize bivariate data with noise
+ *
+ * The vtkBivariateNoiseRepresentation allows to visualize bivariate data with Perlin noise.
+ * Please see the vtkBivariateNoiseMapper documentation for more information.
+ *
+ * @sa vtkBivariateNoiseMapper
+ */
+#ifndef vtkBivariateNoiseRepresentation_h
+#define vtkBivariateNoiseRepresentation_h
+
+#include "vtkBivariateRepresentationsModule.h" // for export macro
+#include "vtkGeometryRepresentationWithFaces.h"
+
+class VTKBIVARIATEREPRESENTATIONS_EXPORT vtkBivariateNoiseRepresentation
+  : public vtkGeometryRepresentationWithFaces
+{
+public:
+  static vtkBivariateNoiseRepresentation* New();
+  vtkTypeMacro(vtkBivariateNoiseRepresentation, vtkGeometryRepresentationWithFaces);
+  void PrintSelf(ostream& os, vtkIndent indent) override;
+
+  /**
+   * Overriden to pass the noise array to the mapper (if idx == 1).
+   */
+  using Superclass::SetInputArrayToProcess; // Force overload lookup on superclass
+  void SetInputArrayToProcess(int idx, int port, int connection, int fieldAssociation,
+    const char* attributeTypeorName) override;
+
+  ///@{
+  /**
+   * Noise parameters.
+   * Forwarded to the mapper.
+   */
+  void SetFrequency(double fMod);
+  void SetAmplitude(double aMod);
+  void SetSpeed(double sMod);
+  void SetNbOfOctaves(int nbOctaves);
+  ///@}
+
+protected:
+  vtkBivariateNoiseRepresentation();
+  ~vtkBivariateNoiseRepresentation() override;
+
+private:
+  vtkBivariateNoiseRepresentation(const vtkBivariateNoiseRepresentation&) = delete;
+  void operator=(const vtkBivariateNoiseRepresentation&) = delete;
+};
+
+#endif
diff --git a/src/Plugins/BivariateRepresentations/Plugin/Testing/BivariateNoiseRepresentation.xml b/src/Plugins/BivariateRepresentations/Plugin/Testing/BivariateNoiseRepresentation.xml
new file mode 100644 (file)
index 0000000..42c3ca8
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" ?>
+<pqevents>
+  <!-- Setup scene (sphere source) -->
+  <pqevent object="pqClientMainWindow/menubar" command="activate" arguments="menuSources" />
+  <pqevent object="pqClientMainWindow/menubar/menuSources" command="activate" arguments="&amp;Geometric Shapes" />
+  <pqevent object="pqClientMainWindow/menubar/menuSources/GeometricShapes" command="activate" arguments="SphereSource" />
+  <pqevent object="pqClientMainWindow/propertiesDock/propertiesPanel/Accept" command="activate" arguments="" />
+  <pqevent object="pqClientMainWindow/cameraToolbar/actionResetCameraClosest" command="activate" arguments="" />
+
+  <!-- Apply elevation filter -->
+  <pqevent object="pqClientMainWindow/menubar" command="activate" arguments="menuFilters" />
+  <pqevent object="pqClientMainWindow/menubar/menuFilters" command="activate" arguments="&amp;Alphabetical" />
+  <pqevent object="pqClientMainWindow/menubar/menuFilters/Alphabetical" command="activate" arguments="ElevationFilter" />
+  <pqevent object="pqClientMainWindow/propertiesDock/propertiesPanel/scrollArea/qt_scrollarea_viewport/scrollAreaWidgetContents/PropertiesFrame/ProxyPanel/InteractiveLine/point1X" command="set_string" arguments="0.0" />
+  <pqevent object="pqClientMainWindow/propertiesDock/propertiesPanel/scrollArea/qt_scrollarea_viewport/scrollAreaWidgetContents/PropertiesFrame/ProxyPanel/InteractiveLine/point2X" command="set_string" arguments="0.0" />
+  <pqevent object="pqClientMainWindow/propertiesDock/propertiesPanel/scrollArea/qt_scrollarea_viewport/scrollAreaWidgetContents/PropertiesFrame/ProxyPanel/InteractiveLine/point1Y" command="set_string" arguments="-0.5" />
+  <pqevent object="pqClientMainWindow/propertiesDock/propertiesPanel/scrollArea/qt_scrollarea_viewport/scrollAreaWidgetContents/PropertiesFrame/ProxyPanel/InteractiveLine/point2Y" command="set_string" arguments="0.5" />
+  <pqevent object="pqClientMainWindow/propertiesDock/propertiesPanel/scrollArea/qt_scrollarea_viewport/scrollAreaWidgetContents/PropertiesFrame/ProxyPanel/InteractiveLine/point1Z" command="set_string" arguments="0.0" />
+  <pqevent object="pqClientMainWindow/propertiesDock/propertiesPanel/scrollArea/qt_scrollarea_viewport/scrollAreaWidgetContents/PropertiesFrame/ProxyPanel/InteractiveLine/point2Z" command="set_string" arguments="0.0" />
+  <pqevent object="pqClientMainWindow/propertiesDock/propertiesPanel/Accept" command="activate" arguments="" />
+  <pqevent object="pqClientMainWindow/propertiesDock/propertiesPanel/Accept" command="activate" arguments="" />
+  <pqevent object="pqClientMainWindow/propertiesDock/propertiesPanel/scrollArea/qt_scrollarea_viewport/scrollAreaWidgetContents/PropertiesFrame/ProxyPanel/InteractiveLine/show3DWidget" command="set_boolean" arguments="false" />
+
+  <!-- Test bivariate noise representation, set speed to 0 to have deterministic output -->
+  <pqevent object="pqClientMainWindow/representationToolbar/displayRepresentation/comboBox" command="activated" arguments="Bivariate Noise Surface" />
+  <pqevent object="pqClientMainWindow/propertiesDock/propertiesPanel/scrollArea/qt_scrollarea_viewport/scrollAreaWidgetContents/DisplayFrame/ProxyPanel/AnimationSpeedFactor/DoubleRangeWidget/DoubleLineEdit" command="set_string" arguments="0" />
+  <pqcompareview object="pqClientMainWindow/centralwidget/MultiViewWidget/CoreWidget/qt_tabwidget_stackedwidget/MultiViewWidget1/Container/Frame.0/CentralWidgetFrame/Viewport/1QVTKOpenGLNativeWidget0" baseline="$PARAVIEW_DATA_ROOT/Plugins/BivariateRepresentations/Testing/Data/Baseline/BivariateNoise_A.png" threshold="5" />
+
+  <!-- Test frequency parameter -->
+  <pqevent object="pqClientMainWindow/propertiesDock/propertiesPanel/scrollArea/qt_scrollarea_viewport/scrollAreaWidgetContents/DisplayFrame/ProxyPanel/Granularity/DoubleRangeWidget/DoubleLineEdit" command="set_string" arguments="50" />
+  <pqcompareview object="pqClientMainWindow/centralwidget/MultiViewWidget/CoreWidget/qt_tabwidget_stackedwidget/MultiViewWidget1/Container/Frame.0/CentralWidgetFrame/Viewport/1QVTKOpenGLNativeWidget0" baseline="$PARAVIEW_DATA_ROOT/Plugins/BivariateRepresentations/Testing/Data/Baseline/BivariateNoise_B.png" threshold="5" />
+
+  <!-- Test amplitude parameter -->
+  <pqevent object="pqClientMainWindow/propertiesDock/propertiesPanel/scrollArea/qt_scrollarea_viewport/scrollAreaWidgetContents/DisplayFrame/ProxyPanel/Granularity/DoubleRangeWidget/DoubleLineEdit" command="set_string" arguments="30" />
+  <pqevent object="pqClientMainWindow/propertiesDock/propertiesPanel/scrollArea/qt_scrollarea_viewport/scrollAreaWidgetContents/DisplayFrame/ProxyPanel/Amplitude/DoubleRangeWidget/DoubleLineEdit" command="set_string" arguments="1" />
+  <pqcompareview object="pqClientMainWindow/centralwidget/MultiViewWidget/CoreWidget/qt_tabwidget_stackedwidget/MultiViewWidget1/Container/Frame.0/CentralWidgetFrame/Viewport/1QVTKOpenGLNativeWidget0" baseline="$PARAVIEW_DATA_ROOT/Plugins/BivariateRepresentations/Testing/Data/Baseline/BivariateNoise_C.png" threshold="5" />
+
+  <!-- Test nb of octaves parameter -->
+  <pqevent object="pqClientMainWindow/propertiesDock/propertiesPanel/scrollArea/qt_scrollarea_viewport/scrollAreaWidgetContents/DisplayFrame/ProxyPanel/Amplitude/DoubleRangeWidget/DoubleLineEdit" command="set_string" arguments="0.5" />
+  <pqevent object="pqClientMainWindow/propertiesDock/propertiesPanel/scrollArea/qt_scrollarea_viewport/scrollAreaWidgetContents/DisplayFrame/ProxyPanel/NbOfOctaves/IntRangeWidget/LineEdit" command="set_string" arguments="1" />
+  <pqcompareview object="pqClientMainWindow/centralwidget/MultiViewWidget/CoreWidget/qt_tabwidget_stackedwidget/MultiViewWidget1/Container/Frame.0/CentralWidgetFrame/Viewport/1QVTKOpenGLNativeWidget0" baseline="$PARAVIEW_DATA_ROOT/Plugins/BivariateRepresentations/Testing/Data/Baseline/BivariateNoise_D.png" threshold="5" />
+</pqevents>
diff --git a/src/Plugins/BivariateRepresentations/Plugin/Testing/CMakeLists.txt b/src/Plugins/BivariateRepresentations/Plugin/Testing/CMakeLists.txt
new file mode 100644 (file)
index 0000000..553494c
--- /dev/null
@@ -0,0 +1,10 @@
+ExternalData_Expand_Arguments("ParaViewData" _
+  "DATA{Data/Baseline/BivariateNoise_A.png}"
+  "DATA{Data/Baseline/BivariateNoise_B.png}"
+  "DATA{Data/Baseline/BivariateNoise_C.png}"
+  "DATA{Data/Baseline/BivariateNoise_D.png}")
+
+paraview_add_client_tests(
+  LOAD_PLUGIN "BivariateRepresentations"
+  TEST_DATA_TARGET ParaViewData
+  TEST_SCRIPTS BivariateNoiseRepresentation.xml)
diff --git a/src/Plugins/BivariateRepresentations/Plugin/Testing/Data/Baseline/BivariateNoise_A.png.sha512 b/src/Plugins/BivariateRepresentations/Plugin/Testing/Data/Baseline/BivariateNoise_A.png.sha512
new file mode 100644 (file)
index 0000000..8242af9
--- /dev/null
@@ -0,0 +1 @@
+3522207f27f6aeda1d9b64a04f0b5e2cdd8faf730a8e722a9512d0d59876dc662a61bec1a0b17745afcd24260c41cff55ba03e2f68b13424d5ffbcf029425ebd
diff --git a/src/Plugins/BivariateRepresentations/Plugin/Testing/Data/Baseline/BivariateNoise_B.png.sha512 b/src/Plugins/BivariateRepresentations/Plugin/Testing/Data/Baseline/BivariateNoise_B.png.sha512
new file mode 100644 (file)
index 0000000..b788e69
--- /dev/null
@@ -0,0 +1 @@
+a2ac03c2a5c319845d1be771c02c644615a0580a13188f2d7c0546eb6d2eeca28324cd067b7eeb8c155a6edbda0a5fea144e6dbfc6164af071e280cbb668ed96
diff --git a/src/Plugins/BivariateRepresentations/Plugin/Testing/Data/Baseline/BivariateNoise_C.png.sha512 b/src/Plugins/BivariateRepresentations/Plugin/Testing/Data/Baseline/BivariateNoise_C.png.sha512
new file mode 100644 (file)
index 0000000..6ffba08
--- /dev/null
@@ -0,0 +1 @@
+2ba6698794cebfde6bd73824b05fcdd1f6c70d6d4f0de7edc1b97b988cbf31359c97e23ab1ffb1043f4b247f548ef974df75801e77c93bdbd408b5ba19d624c3
diff --git a/src/Plugins/BivariateRepresentations/Plugin/Testing/Data/Baseline/BivariateNoise_D.png.sha512 b/src/Plugins/BivariateRepresentations/Plugin/Testing/Data/Baseline/BivariateNoise_D.png.sha512
new file mode 100644 (file)
index 0000000..6f4a38f
--- /dev/null
@@ -0,0 +1 @@
+5fc8358e11c379c6c7491898f62990adeddaa0289f9011b708b7baac40d1393ec31c9aa621c7cd859bda71ebb1bdb39d6ed69d466ad73e0aada313a8dfdb83a3
diff --git a/src/Plugins/BivariateRepresentations/Plugin/paraview.plugin b/src/Plugins/BivariateRepresentations/Plugin/paraview.plugin
new file mode 100644 (file)
index 0000000..19757eb
--- /dev/null
@@ -0,0 +1,8 @@
+NAME
+  BivariateRepresentations
+DESCRIPTION
+  Representations to visualize bivariate data
+REQUIRES_MODULES
+  ParaView::RemotingViews
+  VTK::CommonCore
+  VTK::RenderingOpenGL2
diff --git a/src/Plugins/BivariateRepresentations/Plugin/pqBivariateAnimationManager.cxx b/src/Plugins/BivariateRepresentations/Plugin/pqBivariateAnimationManager.cxx
new file mode 100644 (file)
index 0000000..6defd02
--- /dev/null
@@ -0,0 +1,102 @@
+/*=========================================================================
+
+   Program: ParaView
+   Module: pqBivariateAnimationManager.cxx
+
+   Copyright (c) 2005,2006 Sandia Corporation, Kitware Inc.
+   All rights reserved.
+
+   ParaView is a free software; you can redistribute it and/or modify it
+   under the terms of the ParaView license version 1.2.
+
+   See License_v1.2.txt for the full ParaView license.
+   A copy of this license can be obtained by contacting
+   Kitware Inc.
+   28 Corporate Drive
+   Clifton Park, NY 12065
+   USA
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+========================================================================*/
+#include "pqBivariateAnimationManager.h"
+
+#include "pqApplicationCore.h"
+#include "pqRenderView.h"
+#include "pqRepresentation.h"
+#include "pqServerManagerModel.h"
+#include "pqView.h"
+
+#include "vtkSMPropertyHelper.h"
+#include "vtkSMRepresentationProxy.h"
+
+//-----------------------------------------------------------------------------
+pqBivariateAnimationManager::pqBivariateAnimationManager(QObject* p)
+  : QObject(p)
+{
+  pqServerManagerModel* smmodel = pqApplicationCore::instance()->getServerManagerModel();
+  QObject::connect(smmodel, SIGNAL(preViewAdded(pqView*)), this, SLOT(onViewAdded(pqView*)));
+  QObject::connect(smmodel, SIGNAL(preViewRemoved(pqView*)), this, SLOT(onViewRemoved(pqView*)));
+
+  // Add currently existing views
+  for (pqView* view : smmodel->findItems<pqView*>())
+  {
+    this->onViewAdded(view);
+  }
+}
+
+//-----------------------------------------------------------------------------
+pqBivariateAnimationManager::~pqBivariateAnimationManager() = default;
+
+//-----------------------------------------------------------------------------
+void pqBivariateAnimationManager::onRenderEnded()
+{
+  pqView* view = dynamic_cast<pqView*>(QObject::sender());
+  QList<pqRepresentation*> reprs = view->getRepresentations();
+  for (int i = 0; i < reprs.count(); ++i)
+  {
+    vtkSMRepresentationProxy* repr = vtkSMRepresentationProxy::SafeDownCast(reprs[i]->getProxy());
+    if (repr && repr->GetProperty("Representation"))
+    {
+      const char* rs = vtkSMPropertyHelper(repr, "Representation").GetAsString();
+      const int visible = vtkSMPropertyHelper(repr, "Visibility").GetAsInt();
+      if (rs && !strcmp(rs, "Bivariate Noise Surface") && visible)
+      {
+        // If the view has a visible bivariate noise representation,
+        // then ask for a new render.
+        view->render();
+        break;
+      }
+    }
+  }
+}
+
+//-----------------------------------------------------------------------------
+void pqBivariateAnimationManager::onViewAdded(pqView* view)
+{
+  if (dynamic_cast<pqRenderView*>(view))
+  {
+    this->Views.insert(view);
+    QObject::connect(view, SIGNAL(endRender()), this, SLOT(onRenderEnded()));
+  }
+}
+
+//-----------------------------------------------------------------------------
+void pqBivariateAnimationManager::onViewRemoved(pqView* view)
+{
+  if (dynamic_cast<pqRenderView*>(view))
+  {
+    QObject::disconnect(view, SIGNAL(endRender()), this, SLOT(onRenderEnded()));
+    this->Views.erase(view);
+  }
+}
diff --git a/src/Plugins/BivariateRepresentations/Plugin/pqBivariateAnimationManager.h b/src/Plugins/BivariateRepresentations/Plugin/pqBivariateAnimationManager.h
new file mode 100644 (file)
index 0000000..0937301
--- /dev/null
@@ -0,0 +1,78 @@
+/*=========================================================================
+
+   Program: ParaView
+   Module:    pqBivariateAnimationManager.h
+
+   Copyright (c) 2005,2006 Sandia Corporation, Kitware Inc.
+   All rights reserved.
+
+   ParaView is a free software; you can redistribute it and/or modify it
+   under the terms of the ParaView license version 1.2.
+
+   See License_v1.2.txt for the full ParaView license.
+   A copy of this license can be obtained by contacting
+   Kitware Inc.
+   28 Corporate Drive
+   Clifton Park, NY 12065
+   USA
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+========================================================================*/
+/**
+ * @class   pqBivariateAnimationManager
+ * @brief   Manage animation of the vtkBivariateNoiseRepresentation.
+ *
+ * This class observes every representation of pqRenderView instances when
+ * a rendering pass ends. If a representation of type Bivariate Noise Surface
+ * is found, then render() is triggered to ensure the next update of the simulation.
+ *
+ * @sa vtkBivariateNoiseRepresentation pqStreamLinesAnimationManager
+ */
+
+#ifndef pqBivariateAnimationManager_h
+#define pqBivariateAnimationManager_h
+
+#include <QObject>
+
+#include <set>
+
+class pqView;
+
+class pqBivariateAnimationManager : public QObject
+{
+  Q_OBJECT
+  typedef QObject Superclass;
+
+public:
+  pqBivariateAnimationManager(QObject* p = nullptr);
+  ~pqBivariateAnimationManager() override;
+
+  void onShutdown() {}
+  void onStartup() {}
+
+public Q_SLOTS: // NOLINT(readability-redundant-access-specifiers)
+  void onViewAdded(pqView*);
+  void onViewRemoved(pqView*);
+
+protected Q_SLOTS:
+  void onRenderEnded();
+
+protected: // NOLINT(readability-redundant-access-specifiers)
+  std::set<pqView*> Views;
+
+private:
+  Q_DISABLE_COPY(pqBivariateAnimationManager)
+};
+
+#endif
diff --git a/src/Plugins/BivariateRepresentations/README.md b/src/Plugins/BivariateRepresentations/README.md
new file mode 100644 (file)
index 0000000..3666230
--- /dev/null
@@ -0,0 +1 @@
+# BivariateRepresentations ParaView Plugin
index 9cfe8fe16d328e0ae16959174d89d43d216a8938..efe831b2d02ef79577de6f7dcebac351c28cb476 100644 (file)
@@ -32,6 +32,7 @@ SET(_subdirs
   StaticMesh
   GaussToCell
   VoroGauss
+  BivariateRepresentations
   )
 
 IF(NOT SALOME_LIGHT_ONLY)