Cocoa for Scientists (Part XVI): Finalizing 3D Visualization

Author: Drew McCormack
Website: http://www.maccoremac.com

This is the third and final tutorial on integrating the VTK 3D visualization libraries into a Cocoa application. In part 1, we setup the Xcode project; in part 2, we added source code for our model and controller; and this time round we are going to work in Interface Builder to finish off the UI, and hopefully end up with a simple, but functional, Cocoa-VTK application.

Importing Classes

If you have been following along in your own project, open it up now. Otherwise, you can download the source code from last time, and use that as a starting point.

The first step is to import the various classes that were written last time into Interface Builder (IB), so that IB knows about the actions and outlets available. Begin by double clicking on the MoleculeDocument.nib file in the Resources group in the Groups & Files tree on the left of the Xcode project window. You should see Interface Builder start up, and a single document window appear with the text ‘Your document contents here’. We need to remove that text, so click on it to select, and press backspace to remove it.

To import the vtkCocoaGLView class, click on the Classes tab in the MoleculeDocument.nib window, and choose the Classes > Read Files… menu item. Navigate to the include files directory of your VTK installation, choose the vtkCocoaGLView.h file, and press the Parse button.

For the classes in the Xcode project, it is easier just to drag them into IB. Locate the MoleculeDocument.h file in the Groups & Files tree of Xcode, and drag it to the MoleculeDocument.nib window in IB. Repeat for the BasicVTKView.h file.

Laying Out the Window

Now we need to start adding the elements of the UI. We are aiming for something like what is shown in the screenshot below.

The UI of Animoltion in Interface Builder.

First, change the nib files owner to an instance of the MoleculeDocument class. The file owner is the object that loads the nib file; in this case, it is our MoleculeDocument.

  1. Click on the Instances tab of the MoleculeDocument.nib window.
  2. Select the File’s Owner icon.
  3. Bring up the inspector using the key combination Command-Shift-I.
  4. Select Custom Class from the popup button in the Inspector.
  5. Choose MoleculeDocument from the list of classes.

We will now move to the document window itself. For simplicity, we will prevent the user from resizing the window. To do this:

  1. Click on Window in the Instances tab of the MoleculeDocument.nib window.
  2. Select Attributes from the popup button in the Inspector.
  3. Uncheck the Zoom checkbox to prevent resizing.

We need a custom view now, which will be used for the 3D visualization. This will be an instance of the BasicVTKView class.

  1. Open the IB palettes window by choosing Tools > Palettes > Show Palettes.
  2. Find the Cocoa Container Views tab. This is usually sixth from the left.
  3. Drag the CustomView onto the document window.
  4. Click on the CustomView to select it, and resize it to fit in the window, leaving space at the bottom for other controls (see screenshot above).
  5. With the custom view selected, bring up the inspector using Command-Shift-I.
  6. From the Inspector’s popup button, choose Custom Class.
  7. Choose BasicVTKView from the list of classes.

Now we need a slider, to control spring stiffness between the atoms, and a button to stop and start the animation.

  1. Go to the Cocoa Controls palette (usually second from the left).
  2. Drag the standard glass button in the top left corner to the bottom of the window.
  3. Bring up the Inspector, and choose Attributes from the popup button.
  4. Enter ‘Play’ for the Title, and ‘Pause’ for Alt. Title.
  5. Choose ‘Rounded Bevel Button’ from the Type popup, and then ‘Toggle’ from the Behavior popup.

For the slider, follow this procedure:

  1. Drag a slider from the same palette used for the button, and center it above the button (see screenshot above).
  2. Select the slider, and choose the Attributes pane in the Inspector.
  3. Setup the attributes of the slider as shown in the screen shot below. The most important settings are the Minimum (0.5), the Maximum (2.0), and Current (1.0).

Slider Attributes.

Connecting it up

All that is left to do is connect up the various actions and outlets defined in our controller class. We’ll begin by connecting the vtkView outlet of the MoleculeDocument instance to the custom view in the document window:

  1. Hold down the Control key and drag from File’s Owner in the MoleculeDocument.nib document to the BasicVTKView in the document window (see screenshot below).
  2. Choose Connections in the Inspector popup button, and then select the Outlets tab.
  3. Select the vtkView outlet, and click the Connect button.

Connecting the vtkView Outlet.

Now we need to connect up the Play button, so that when it is pressed, the animation is stopped or started appropriately.

  1. Control-drag from the File’s Owner icon to the Play button, and choose playStateButton outlet in the Inspector, and press Connect.
  2. Control drag from the slider to the File’s Owner. Select the Target/Action tab in the Connections pane of the inspector, select updateStiffness:, and press Connect.
  3. Control drag from the Play button to the File’s Owner, select the togglePlayState: action, and press Connect.

Now save your changes, return to Xcode, and press the Build and Go button. Hopefully you will see the complete Animoltion app.

If you just want the complete source code, download it here.

Animolting

Animoltion is not exactly rocket science. Just press Play to start the animation and Stop to pause. Pressing Play again will cause the animation to continue from where it was paused.

The stiffness slider has until now been somewhat mysterious. If you move the slider to the right, you should see the molecule become stiffer, with the atoms vibrating more rapidly but not moving as far. Moving the slider to the left makes the molecule more floppy, with the atoms vibrating less rapidly, and traveling farther.

Apart from the controls we have built into Animoltion, VTK brings several of its own to the table. Clicking and dragging on the 3D view rotates the molecule, for example. Control-Shift-click and drag up or down zooms in and out. Shift-click and drag translates the view sideways. Control-click and drag causes the view to rotate around the line of sight.

Sometimes you will notice that the atoms move outside the view, or come too close to the camera and are chopped off. In such instances you can press “r”, to reset the camera location. You might also try pressing “w”, which shows the atoms in wireframe; pressing “s” makes them solid again.

Scratching VTK’s Surface

In the comments of the last tutorial, Justin Mitchell posed the question: ‘What can you do with VTK that you can’t just do with OpenGL directly?’ Good question. Here is my response:

Of course, I have chosen a very simple example, one that is quite simple to do in OpenGL, since it only works with spheres. But VTK has much more, and it is nearly all about visualizing data. OpenGL just gives you the primitives to draw with; VTK tells you what to draw. It’s like the difference between a 2D graphics engine like Quartz 2D, and a plotting framework. The plotting framework sits on top of the drawing engine.

Just to get you a bit of an idea of some of the things you can do with VTK, take the example of a scalar field or density. With maybe 20 lines of VTK code, you can generate an isosurface or volume rendering of the data, complete with user interaction (rotating, translating etc). With another 20 lines or so, you could add a cut plane to it. The point is not that you can’t do this with OpenGL yourself, but it will take you thousands of lines. Effectively you will be implementing the same sorts of algorithms (eg marching cubes) that are already built into VTK.

That’s it for this little foray into 3D visualization in Cocoa. I have concentrated on the technical aspects of just getting VTK integrated into a Cocoa app, and haven’t spent much time on VTK itself. We are working on getting a few tutorials on VTK itself, so stay tuned if this is something that interests you.

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

No document could be created

My Animoltion compiles with 2 warnings. They are the same:
At #import "BasicVTKView.h" in BasicVTKView.mm and
at #import "MoleculeDocument.h" in MoleculeDocument.mm

The warning begins, "This file contains at least one depracated or antiquated header. ..."

I ignored the warnings and ran the application, which launches and immediately opens a window stating, "No document could be created."

So now I am debugging, but I would appreciate anyone's suggestions.

Adam

No documents

Hi Adam,

I think I saw the warnings too. They are harmless I think.

It's an odd problem. I have never seen anything like that. Do you get messages in the run log?

What happens when you download and try to compile my version? Or did you already do that?

You need to make sure that any reference to MyDocument has been removed from your source code and Info.plist file etc. Use project find to locate any of those.

Drew

---------------------------
Drew McCormack
http://www.maccoremac.com
http://www.macanics.net
http://www.macresearch.org

Correct

I went back through the tutorials and found a "MyDocument" reference that I had missed, so well spotted. Alas, I am on to my next error:

"Could not find file /Users/adam/Projects/Animoltion/asm -[NSWindowController showWindow:] 0x9388c1c0. Perhaps it was moved or deleted?"

That sounds like I changed the wrong path somewhere - still working on it.

Adam

Build Problem on Intel-Only

Thanks for the tutorials. Looking forward to more VTK.

When building the example on an Intel Mac Pro, I found that in Debug configuration, that it would compile, but then fail at run time with a Bad Access error. It was failing to load the VTK libraries. (I had previously built and installed the VTK libraries as indicated in the first tutorial but only for Intel.)

Further I found that switching to Release configuration, the link would fail with several missing symbols and several messages like this:

/usr/bin/ld: warning /usr/local/VTK/cocoa/lib/libvtkzlib.a archive's cputype (7, architecture i386) does not match cputype (18) for specified -arch flag: ppc (can't load from it)

I didn't have ppc turned on anywhere in XCode that I could find. I tried building from the command line with xcodebuild and got the same errors.

What I found I could do was to edit the project.pbxproj file in the Project's .xcodeproj package directory. I removed any ppc entries. It now compiles from both command line and from XCode in Release mode and runs perfectly. (I still have a Bad Access error in Debug config.)

Thought I would pass along in case somebody else ran into the same problems or knew a better solution.

Re: Build Problem on Intel-Only

I've been banging my head with the same problem. I greatly appreciate the tip, but I'm also eager I find a more permanent solution (one where I can use a debuger). Any ideas out there?

Re: Build Problem on Intel-Only

Hi Guys,

I haven't tried building on Intel, but I did poke around in the project looking for some reason for your issues. The first thing to note is that in the Animoltion target build options (double click to edit), if you select 'Release', it includes two plaforms: ppc and i386. With the current release version of VTK, you can't build universal binaries, so you will want to uncheck one of the platforms if you are using the release config.

The second thing to remember is to turn off ZeroLink. It causes a lot of problems. Make sure you do this in debug and release mode. It may very well be that the reason for your crashes in debug mode is ZeroLink.

Drew

---------------------------
Drew McCormack
http://www.maccoremac.com
http://www.macanics.net
http://www.macresearch.org

Intel VTK now works - weird

Drew, you were right, but not for the reason you think. You're suggestions were the first thing I checked some time ago. I changed the build instructions from within Xcode to make an i386 only app with no Zerolink.
Xcode was still unconvinced. Even after cleaning the build products from within the debugger OR deleting the project's build folder from Finder, Xcode would make new i386 AND ppc build folders. This problem only affected Release mode.
I took Jeff's suggestion and changed the project.pbxproj file directly. This got the Release mode to work. Poking in the same file, I found that Zerolink was still turned on for debug mode. After switching that part, everything works great. (Jeff, try to see if that is the case on yours.)
I have no idea why Xcode isn't updating the project.pbxproj file, but that seems to be the issue.
Unless somebody can think of something I screwed up, I'll be submitting a very confusing (and confused) bug report to apple.

Justin

Re: Intel VTK now works - weird

Hi Justin,

Good to hear it works. I'm not sure if you have come across a bug in Xcode or not. It is very easy to miss these settings, because they are set a the project level (double click the project icon), and at the target level (double click target), and they are set for each different config. in the project. It's easy to get confused. Not saying that is happening here, but it is a possible explanation.

Regards,
Drew

---------------------------
Drew McCormack
http://www.maccoremac.com
http://www.macanics.net
http://www.macresearch.org

Warnings

Hi Drew (and Adam)

I have a MacBook Pro (2.33Ghz - 2Gig Ram). I downloaded your project and compiled it. I got the same errors everybody got.
To eliminate the ppc related error I went to "Edit Project Settingns" in the Project menu, double clicked the Architecture option and selected i386 (intel). I did the same with "Edit Active Target 'Animoltion' ". I didn't have to chance the Zero-Link option since it was already unchecked.
With the change, I got the program to run but with the two warnings. To get rid of those, go to "Edit Active Target 'Animoltion' " in the project menu. Scroll down and find "Other C++ flags". Double click it and write: -Wno-deprecated after the $(inherited). This will take care of the warnings.

Hope this helps. Thanks for the tutorial. Keep them coming!

neomancer