Redirect vtkContextView to a chosen render window

I want to use vtkChartXYZ in Java, as demonstrated by the SurfacePlot example which can be ported to java almost as-is.

The example uses a vtkContextView which facilitate the renderer, render window and interactor initialization among other things. Once started, this example opens a system window.

Since I want the chart to be included in a Java AWT application, I need to somehow redirect the render window of the vtkContextView to the render window of a JOGL Component.

I tried two ways which do not work, could someone drive me to a better way?

vtkChartXYZ chart = new vtkChartXYZ();
vtkPlotSurface plot = new vtkPlotSurface();
vtkContextView view = new vtkContextView();

// First attempt will fail with a cast exception. The render window returned by vtkContextView
// is in this case a vtkWin32OpenGLRenderWindow. The vtkJoglPanelComponent is expecting
// a vtkRenderWindow of type vtkGenericOpenGLRenderWindow, which is not a superclass
// of vtkWin32OpenGLRenderWindow : https://vtk.org/doc/nightly/html/classvtkRenderWindow.html
vtkAbstractJoglComponent<?> jogl = new vtkJoglPanelComponent(view.GetRenderWindow());

// Second attempt will fail with a JVM crash
vtkAbstractJoglComponent<?> jogl = new vtkJoglPanelComponent();
view.SetRenderWindow(jogl.getRenderWindow());
view.SetRenderer(jogl.getRenderer());
...
view.GetRenderWindow().Render(); // crashes here

2022-09-17 10:48:25.647 (   3.524s) [                ]vtkGenericOpenGLRenderW:205    ERR| vtkGenericOpenGLRenderWindow (0000020844C0E230): error before running VTK rendering code 16 OpenGL errors detected
  0 : (1282) Invalid operation
  1 : (1282) Invalid operation
  2 : (1282) Invalid operation
  3 : (1282) Invalid operation
  4 : (1282) Invalid operation
  5 : (1282) Invalid operation
  6 : (1282) Invalid operation
  7 : (1282) Invalid operation
  8 : (1282) Invalid operation
  9 : (1282) Invalid operation
  10 : (1282) Invalid operation
  11 : (1282) Invalid operation
  12 : (1282) Invalid operation
  13 : (1282) Invalid operation
  14 : (1282) Invalid operation
  15 : (1282) Invalid operation

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffa5a8408b9, pid=11764, tid=12776
#
# JRE version: OpenJDK Runtime Environment Zulu11.52+13-CA (11.0.13+8) (build 11.0.13+8-LTS)
# Java VM: OpenJDK 64-Bit Server VM Zulu11.52+13-CA (11.0.13+8-LTS, mixed mode, tiered, compressed oops, g1 gc, windows-amd64)
# Problematic frame:
# C  0x00007ffa5a8408b9
#
# No core dump will be written. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\Users\Martin\Dev\jzy3d\public\jzy3d-vtk\hs_err_pid11764.log
2022-09-17 10:48:25.692 (   3.569s) [                ]     vtkOpenGLState.cxx:68    WARN| Error in cache state for GL_DEPTH_WRITEMASK

Hi, Martin,

VTK defines a vtk.vtkRenderWindow class in Java API. Please, take a look at this example: https://kitware.github.io/vtk-examples/site/Java/GeometricObjects/CylinderExample/ .

If you need do add a VTK panel as a widget to the layout of some window or dialog, you can resort to vtk.vtkCanvas: VTK/VTKCanvas.java at master · Kitware/VTK · GitHub .

take care,

Paulo

Thank you Paulo.

I got crashes with vtkCanvas while a vtk JOGL canvas (or panel) works properly across computers running java programs.

But whatever the java canvas used for display (that is, a component on which we can invoke getRenderer() and getRenderWindow()), I haven’t found how to affect them to the vtkContextView object that is demonstrated in the SurfacePlot example.

The vtkContextView source code shows that it has its own renderer and then provides it to the Scene.

I wonder if it is possible to continue using this vtkContextView but to set it a chosen Renderer?

I extended my example above to set the Scene’s Renderer but it still crashes the JVM the same way.

vtkAbstractJoglComponent<?> jogl = new vtkJoglPanelComponent();
view.SetRenderWindow(jogl.getRenderWindow());
view.SetRenderer(jogl.getRenderer());
view.GetScene(jogl.getRenderer());

Hello,

Is there any particular reason to use vtkContextView besides being a low-code method for 2D charts in VTK?

cheers,

Paulo

The reason is that the example program demonstrating vtkChartXYZ uses it. The LinePlot3D example - the only other example of vtkChartXYZ also refers to vtkContextView.

I tried removing vtkContextView from the example and to initialize a renderer, window and interactor as done in the CylinderExample but the window appears empty. I also tried adding a vtkContextScene (that the vtkContextView references and uses to register the vtkChartXYZ) but it did nothing. Here is what I got at the end :

package vtk.examples.surface;

import ch.unibas.cs.gravis.vtkjavanativelibs.VtkJavaNativeLibraryException;
import ch.unibas.cs.gravis.vtkjavanativelibs.VtkNativeLibraries;
import vtk.vtkChartXYZ;
import vtk.vtkContextScene;
import vtk.vtkFloatArray;
import vtk.vtkNamedColors;
import vtk.vtkPlotSurface;
import vtk.vtkRenderWindow;
import vtk.vtkRenderWindowInteractor;
import vtk.vtkRenderer;
import vtk.vtkTable;

public class DemoVTKSurfaceChartNoContext {

  public static void main(String[] args) throws VtkJavaNativeLibraryException {
    VtkNativeLibraries.initialize();

    vtkNamedColors colors = new vtkNamedColors();
    vtkChartXYZ chart = new vtkChartXYZ();
    vtkPlotSurface plot = new vtkPlotSurface();
    vtkRenderer renderer = new vtkRenderer();
    vtkRenderWindow window = new vtkRenderWindow();

    vtkContextScene scene = new vtkContextScene();
    scene.SetRenderer(renderer);
    scene.AddItem(chart);

    // Create a surface
    vtkTable table = new vtkTable();
    int numPoints = 70;
    float inc = 9.424778f / (numPoints - 1);
    for (int i = 0; i < numPoints; ++i) {
      vtkFloatArray arr = new vtkFloatArray();
      table.AddColumn(arr);
    }

    table.SetNumberOfRows(numPoints);
    for (int i = 0; i < numPoints; ++i) {
      float x = i * inc;
      for (int j = 0; j < numPoints; ++j) {
        float y = j * inc;

        float value = (float) Math.sin(Math.sqrt(x * x + y * y));

        ((vtkFloatArray) table.GetColumn(j)).SetValue(i, value);
      }
    }

    // Set up the surface plot we wish to visualize and add it to the chart.
    plot.SetXRange(0f, 10.0f);
    plot.SetYRange(0f, 10.0f);
    plot.SetInputData(table);

    // Coloring plot and renderer
    double[] color2 = new double[4];
    colors.GetColor("Tomato", color2);
    plot.GetPen().SetColorF(color2);
    chart.AddPlot(plot);
    
    double[] color = new double[4];
    colors.GetColor("Silver", color);
    renderer.SetBackground(color);

    // Configure window and interactor
    window.AddRenderer(renderer);
    window.SetSize(640, 480);
    window.SetMultiSamples(0);
    window.SetWindowName("SurfacePlot");
    window.Render();

    vtkRenderWindowInteractor interactor = new vtkRenderWindowInteractor();
    interactor.SetRenderWindow(window);
    interactor.Initialize();
    interactor.Start();

  }
}