package vtk; import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.SwingUtilities; public class vtkPanel extends Canvas implements MouseListener, MouseMotionListener, KeyListener { protected vtkRenderWindow rw = new vtkRenderWindow(); protected vtkRenderer ren = new vtkRenderer(); protected vtkCamera cam = null; protected vtkLight lgt = new vtkLight(); protected int lastX; protected int lastY; protected int windowset = 0; protected int lightingset = 0; protected int LightFollowCamera = 1; protected int InteractionMode = 1; protected boolean rendering = false; protected WindowObservable windowSetObservable = new WindowObservable(); static { System.loadLibrary("vtkCommonJava"); System.loadLibrary("vtkFilteringJava"); System.loadLibrary("vtkIOJava"); System.loadLibrary("vtkImagingJava"); System.loadLibrary("vtkGraphicsJava"); System.loadLibrary("vtkRenderingJava"); try { System.loadLibrary("vtkHybridJava"); } catch (Throwable e) { System.out.println("cannot load vtkHybrid, skipping..."); } try { System.loadLibrary("vtkVolumeRenderingJava"); } catch (Throwable e) { System.out.println("cannot load vtkVolumeRendering, skipping..."); } } protected native int RenderCreate(vtkRenderWindow id0); protected native int Lock(); protected native int UnLock(); public vtkPanel() { rw.AddRenderer(ren); addMouseListener(this); addMouseMotionListener(this); addKeyListener(this); super.setSize(200,200); rw.SetSize(200,200); addWindowSetObserver(new WindowSetObserver()); } public void Report() { // must be performed on awt event thread Runnable updateAComponent = new Runnable() { public void run() { Lock(); System.out.println("direct rendering = " + (rw.IsDirect()==1)); System.out.println("opengl supported = " + (rw.SupportsOpenGL()==1)); System.out.println("report = " + rw.ReportCapabilities()); UnLock(); } }; SwingUtilities.invokeLater(updateAComponent); } public vtkRenderer GetRenderer() { return ren; } public vtkRenderWindow GetRenderWindow() { return rw; } public void addWindowSetObserver(Observer obs) { windowSetObservable.addObserver(obs); } public void removeWindowSetObserver(Observer obs) { windowSetObservable.deleteObserver(obs); } public void setSize(int x, int y) { super.setSize(x,y); if (windowset == 1) { Lock(); rw.SetSize(x,y); UnLock(); } } public void addNotify() { super.addNotify(); windowset = 0; rw.SetForceMakeCurrent(); rendering = false; } public void removeNotify() { rendering = true; super.removeNotify(); } public synchronized void Render() { if (!rendering) { rendering = true; if (ren.VisibleActorCount() == 0) {rendering = false; return;} if (rw != null) { if (windowset == 0) { // set the window id and the active camera cam = ren.GetActiveCamera(); if (lightingset == 0) { ren.AddLight(lgt); lgt.SetPosition(cam.GetPosition()); lgt.SetFocalPoint(cam.GetFocalPoint()); lightingset = 1; } RenderCreate(rw); Lock(); rw.SetSize(getWidth(), getHeight()); UnLock(); windowset = 1; // notify observers that we have a renderwindow created windowSetObservable.notifyObservers(); } Lock(); rw.Render(); UnLock(); rendering = false; } } } public boolean isWindowSet() { return (this.windowset==1); } public void paint(Graphics g) { this.Render(); } public void update(Graphics g) { paint(g); } public void LightFollowCameraOn() { this.LightFollowCamera = 1; } public void LightFollowCameraOff() { this.LightFollowCamera = 0; } public void InteractionModeRotate() { this.InteractionMode = 1; } public void InteractionModeTranslate() { this.InteractionMode = 2; } public void InteractionModeZoom() { this.InteractionMode = 3; } public void UpdateLight() { lgt.SetPosition(cam.GetPosition()); lgt.SetFocalPoint(cam.GetFocalPoint()); } public void resetCameraClippingRange() { Lock(); ren.ResetCameraClippingRange(); UnLock(); } public void resetCamera() { Lock(); ren.ResetCamera(); UnLock(); } public void mouseClicked(MouseEvent e) { } public void mousePressed(MouseEvent e) { if (ren.VisibleActorCount() == 0) return; rw.SetDesiredUpdateRate(5.0); lastX = e.getX(); lastY = e.getY(); if ((e.getModifiers()==InputEvent.BUTTON2_MASK) || (e.getModifiers()==(InputEvent.BUTTON1_MASK | InputEvent.SHIFT_MASK))) { InteractionModeTranslate(); } else if (e.getModifiers()==InputEvent.BUTTON3_MASK) { InteractionModeZoom(); } else { InteractionModeRotate(); } } public void mouseReleased(MouseEvent e) { rw.SetDesiredUpdateRate(0.01); } public void mouseEntered(MouseEvent e) { this.requestFocus(); } public void mouseExited(MouseEvent e) {} public void mouseMoved(MouseEvent e) { lastX = e.getX(); lastY = e.getY(); } public void mouseDragged(MouseEvent e) { if (ren.VisibleActorCount() == 0) return; int x = e.getX(); int y = e.getY(); // rotate if (this.InteractionMode == 1) { cam.Azimuth(lastX - x); cam.Elevation(y - lastY); cam.OrthogonalizeViewUp(); resetCameraClippingRange(); if (this.LightFollowCamera == 1) { lgt.SetPosition(cam.GetPosition()); lgt.SetFocalPoint(cam.GetFocalPoint()); } } // translate if (this.InteractionMode == 2) { double FPoint[]; double PPoint[]; double APoint[] = new double[3]; double RPoint[]; double focalDepth; // get the current focal point and position FPoint = cam.GetFocalPoint(); PPoint = cam.GetPosition(); // calculate the focal depth since we'll be using it a lot ren.SetWorldPoint(FPoint[0],FPoint[1],FPoint[2],1.0); ren.WorldToDisplay(); focalDepth = ren.GetDisplayPoint()[2]; APoint[0] = rw.GetSize()[0]/2.0 + (x - lastX); APoint[1] = rw.GetSize()[1]/2.0 - (y - lastY); APoint[2] = focalDepth; ren.SetDisplayPoint(APoint); ren.DisplayToWorld(); RPoint = ren.GetWorldPoint(); if (RPoint[3] != 0.0) { RPoint[0] = RPoint[0]/RPoint[3]; RPoint[1] = RPoint[1]/RPoint[3]; RPoint[2] = RPoint[2]/RPoint[3]; } /* * Compute a translation vector, moving everything 1/2 * the distance to the cursor. (Arbitrary scale factor) */ cam.SetFocalPoint( (FPoint[0]-RPoint[0])/2.0 + FPoint[0], (FPoint[1]-RPoint[1])/2.0 + FPoint[1], (FPoint[2]-RPoint[2])/2.0 + FPoint[2]); cam.SetPosition( (FPoint[0]-RPoint[0])/2.0 + PPoint[0], (FPoint[1]-RPoint[1])/2.0 + PPoint[1], (FPoint[2]-RPoint[2])/2.0 + PPoint[2]); resetCameraClippingRange(); } // zoom if (this.InteractionMode == 3) { double zoomFactor; double clippingRange[]; zoomFactor = Math.pow(1.02,(y - lastY)); if (cam.GetParallelProjection() == 1) { cam.SetParallelScale(cam.GetParallelScale()/zoomFactor); } else { cam.Dolly(zoomFactor); resetCameraClippingRange(); } } lastX = x; lastY = y; this.Render(); } public void keyTyped(KeyEvent e) {} public void keyPressed(KeyEvent e) { if (ren.VisibleActorCount() == 0) return; char keyChar = e.getKeyChar(); if ('r' == keyChar) { resetCamera(); this.Render(); } if ('u' == keyChar) { pickActor(lastX, lastY); } if ('w' == keyChar) { vtkActorCollection ac; vtkActor anActor; vtkActor aPart; int i, j; ac = ren.GetActors(); ac.InitTraversal(); for (i = 0; i < ac.GetNumberOfItems(); i++) { anActor = ac.GetNextActor(); anActor.InitPartTraversal(); for (j = 0; j < anActor.GetNumberOfParts(); j++) { aPart = anActor.GetNextPart(); aPart.GetProperty().SetRepresentationToWireframe(); } } this.Render(); } if ('s' == keyChar) { vtkActorCollection ac; vtkActor anActor; vtkActor aPart; int i, j; ac = ren.GetActors(); ac.InitTraversal(); for (i = 0; i < ac.GetNumberOfItems(); i++) { anActor = ac.GetNextActor(); anActor.InitPartTraversal(); for (j = 0; j < anActor.GetNumberOfParts(); j++) { aPart = anActor.GetNextPart(); aPart.GetProperty().SetRepresentationToSurface(); } } this.Render(); } } public void HardCopy(String filename, int mag) { Lock(); vtkWindowToImageFilter w2if = new vtkWindowToImageFilter(); w2if.SetInput(rw); w2if.SetMagnification(mag); w2if.Update(); vtkTIFFWriter writer = new vtkTIFFWriter(); writer.SetInput(w2if.GetOutput()); writer.SetFileName(filename); writer.Write(); UnLock(); } public void pickActor(int x, int y) { vtkPropPicker picker = new vtkPropPicker(); Lock(); picker.PickProp(x, rw.GetSize()[1] - y , ren); UnLock(); if (picker.GetActor() != null) System.out.println(picker.GetActor().GetClassName()); } public void keyReleased(KeyEvent e) {} private class WindowObservable extends Observable { public void notifyObservers() { this.setChanged(); super.notifyObservers(); } public void notifyObservers(Object message) { this.setChanged(); super.notifyObservers(message); } public boolean hasObservers() { return 0 < super.countObservers(); } } private class WindowSetObserver implements Observer { public void update(Observable o, Object arg) { // we know the window is set, so changes to the render window size // will actually take place // if (getWidth() > 0 && getHeight() > 0) // rw.SetSize(getWidth(), getHeight()); } } }