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
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 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();
}
}