Friday, July 14, 2006

Offscreen rendering with VTK and Java

We are trying to implement a web based tool for looking at slices and some 3d rendering of our MRI fish data (the project is dubbed "Mr Fish" light). My colleague Cameron (Blog) is handling the Ajax/JavaScript/design part and I am doing the backend with VTK/Struts/Tomcat/Java. In a series of Blogs I will explain how to do something like that. In our first installmaent we look at off screen rendering:

To accomplish off screen renderin in VTK you need to install some "mangled version" of Mesa. VTK has a how to here - which sort of describes it. Once you recompiled VTK you are ready to write some Code.

The VTK people essentially recomment instead of using the generic versions of actors, renderers, cameras to use Mesa specific versions. The code to set up the rendering pipeline looks like that:

vtkImageGaussianSmooth smooth = new vtkImageGaussianSmooth();
smooth.SetInput(threshold.GetOutput());
smooth.SetDimensionality(2);
smooth.SetRadiusFactors(1, 1, 0);
//smooth.

// An isosurface, or contour value of 500 is known to correspond to the
// skin of the patient. Once generated, a vtkPolyDataNormals filter is
// is used to create normals for smooth surface shading during rendering.
// The triangle stripper is used to create triangle strips from the
// isosurface these render much faster on some systems.
vtkContourFilter skinExtractor = new vtkContourFilter();
skinExtractor.SetInput(smooth.GetOutput());
skinExtractor.SetValue(0,1150);
vtkPolyDataNormals skinNormals = new vtkPolyDataNormals();
skinNormals.SetInput(skinExtractor.GetOutput());
skinNormals.SetFeatureAngle(60.0);
// vtkStripper skinStripper = new vtkStripper();
//skinStripper.SetInput(skinNormals.GetOutput());
vtkTriangleFilter triangle = new vtkTriangleFilter();
triangle.SetInput(skinNormals.GetOutput());
vtkQuadricDecimation quad = new vtkQuadricDecimation();
quad.SetInput(triangle.GetOutput());
quad.SetTargetReduction(0.2);
vtkMesaPolyDataMapper skinMapper = new vtkMesaPolyDataMapper();
skinMapper.SetInput(quad.GetOutput());
skinMapper.ScalarVisibilityOff();

vtkMesaActor skin = new vtkMesaActor();
skin.SetMapper(skinMapper);
skin.GetProperty().SetDiffuseColor(1, .49, .25);
skin.GetProperty().SetSpecular(.3);
skin.GetProperty().SetSpecularPower(20);
// Set skin to semi-transparent.
skin.GetProperty().SetOpacity(0.5);

vtkMesaCamera aCamera = new vtkMesaCamera();
aCamera.SetViewUp(0, 0, -1);
aCamera.SetPosition(0, 1, 0);
aCamera.SetFocalPoint(0, 0, 0);
aCamera.ComputeViewPlaneNormal();

vtkXMesaRenderWindow renderWin = new vtkXMesaRenderWindow();
renderWin.SetOffScreenRendering(1);

vtkMesaRenderer ren = new vtkMesaRenderer();
renderWin.AddRenderer(ren);

ren.SetActiveCamera(aCamera);

ren.AddActor(skin);
ren.ResetCamera();
ren.ResetCameraClippingRange();

RenderObject ro = new RenderObject();
ro.camera = aCamera;
ro.renWin = renderWin;
ro.ren = ren;
To write that in a file use the following code:

RenderObject ro = renderMap.get(filename);

//move camera
ro.camera.Azimuth(azimuth);
ro.camera.Elevation(elevation);
ro.camera.Roll(roll);
ro.renWin.Render();

vtkWindowToImageFilter w2if = new vtkWindowToImageFilter();
w2if.SetInput(ro.renWin);

// generate tmp file
File tmpFile = File.createTempFile(generateUniqueName(), ".png");
String tmpFilename = tmpFile.getAbsolutePath();

vtkPNGWriter jpg = new vtkPNGWriter();
jpg.SetInput(w2if.GetOutput());
jpg.SetFileName(tmpFilename);
jpg.Write();

//reset Camera
ro.ren.ResetCamera();

return tmpFile;
The render object is just a simple class to hold all those things:

class RenderObject {
public vtkXMesaRenderWindow renWin;
public vtkMesaCamera camera;
public vtkMesaRenderer ren;
}
Stay tuned for the next installment of the project...

0 Comments:

Post a Comment

<< Home