Graphics Programing Pains

By Xah Lee. Date: . Last updated: .

I have a problem. I want to do 3D geometry visualization programing, but there is no appropriate tools. (See: Requirements for a Visualization System) O, faak the industry.

GUI Programing Pain

I never had any experience writing a GUI application. (except web/HTML form based ones, which doesn't really count.) About 3 times in different years since 1997, i tried to learn GUI programing thru Java's Swing framework. But each time i aborted rather even before getting a basic understanding of how to create a menu. Today is another try, and perhaps the furthest i've made. To make a empty window with a menu with no actions attached, requires some faaking 170 lines of java code, and tens of classes and objects with complex relationships.

Sample code:

// the code demonstrates creating a GUI app with a menu bar and 2 menus, each having a few items but no actions attached.

// this code is from
// http://java.sun.com/docs/books/tutorial/uiswing/components/menu.html
// accessed on 2007-12-29

//package components;

import java.awt.*;
import java.awt.event.*;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.ButtonGroup;
import javax.swing.JMenuBar;
import javax.swing.KeyStroke;
import javax.swing.ImageIcon;

import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import javax.swing.JFrame;

/* MenuLookDemo.java requires images/middle.gif. */

/*
 * This class exists solely to show you what menus look like.
 * It has no menu-related event handling.
 */
public class MenuLookDemo {
    JTextArea output;
    JScrollPane scrollPane;

    public JMenuBar createMenuBar() {
        JMenuBar menuBar;
        JMenu menu, submenu;
        JMenuItem menuItem;
        JRadioButtonMenuItem rbMenuItem;
        JCheckBoxMenuItem cbMenuItem;

        //Create the menu bar.
        menuBar = new JMenuBar();

        //Build the first menu.
        menu = new JMenu("A Menu");
        menu.setMnemonic(KeyEvent.VK_A);
        menu.getAccessibleContext().setAccessibleDescription(
                "The only menu in this program that has menu items");
        menuBar.add(menu);

        //a group of JMenuItems
        menuItem = new JMenuItem("A text-only menu item",
                                 KeyEvent.VK_T);
        //menuItem.setMnemonic(KeyEvent.VK_T); //used constructor instead
        menuItem.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_1, ActionEvent.ALT_MASK));
        menuItem.getAccessibleContext().setAccessibleDescription(
                "This doesn't really do anything");
        menu.add(menuItem);

        ImageIcon icon = createImageIcon("images/middle.gif");
        menuItem = new JMenuItem("Both text and icon", icon);
        menuItem.setMnemonic(KeyEvent.VK_B);
        menu.add(menuItem);

        menuItem = new JMenuItem(icon);
        menuItem.setMnemonic(KeyEvent.VK_D);
        menu.add(menuItem);

        //a group of radio button menu items
        menu.addSeparator();
        ButtonGroup group = new ButtonGroup();

        rbMenuItem = new JRadioButtonMenuItem("A radio button menu item");
        rbMenuItem.setSelected(true);
        rbMenuItem.setMnemonic(KeyEvent.VK_R);
        group.add(rbMenuItem);
        menu.add(rbMenuItem);

        rbMenuItem = new JRadioButtonMenuItem("Another one");
        rbMenuItem.setMnemonic(KeyEvent.VK_O);
        group.add(rbMenuItem);
        menu.add(rbMenuItem);

        //a group of check box menu items
        menu.addSeparator();
        cbMenuItem = new JCheckBoxMenuItem("A check box menu item");
        cbMenuItem.setMnemonic(KeyEvent.VK_C);
        menu.add(cbMenuItem);

        cbMenuItem = new JCheckBoxMenuItem("Another one");
        cbMenuItem.setMnemonic(KeyEvent.VK_H);
        menu.add(cbMenuItem);

        //a submenu
        menu.addSeparator();
        submenu = new JMenu("A submenu");
        submenu.setMnemonic(KeyEvent.VK_S);

        menuItem = new JMenuItem("An item in the submenu");
        menuItem.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_2, ActionEvent.ALT_MASK));
        submenu.add(menuItem);

        menuItem = new JMenuItem("Another item");
        submenu.add(menuItem);
        menu.add(submenu);

        //Build second menu in the menu bar.
        menu = new JMenu("Another Menu");
        menu.setMnemonic(KeyEvent.VK_N);
        menu.getAccessibleContext().setAccessibleDescription(
                "This menu does nothing");
        menuBar.add(menu);

        return menuBar;
    }

    public Container createContentPane() {
        //Create the content-pane-to-be.
        JPanel contentPane = new JPanel(new BorderLayout());
        contentPane.setOpaque(true);

        //Create a scrolled text area.
        output = new JTextArea(5, 30);
        output.setEditable(false);
        scrollPane = new JScrollPane(output);

        //Add the text area to the content pane.
        contentPane.add(scrollPane, BorderLayout.CENTER);

        return contentPane;
    }

    /** Returns an ImageIcon, or null if the path was invalid. */
    protected static ImageIcon createImageIcon(String path) {
        java.net.URL imgURL = MenuLookDemo.class.getResource(path);
        if (imgURL != null) {
            return new ImageIcon(imgURL);
        } else {
            System.err.println("Couldn't find file: " + path);
            return null;
        }
    }

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("MenuLookDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Create and set up the content pane.
        MenuLookDemo demo = new MenuLookDemo();
        frame.setJMenuBar(demo.createMenuBar());
        frame.setContentPane(demo.createContentPane());

        //Display the window.
        frame.setSize(450, 260);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

So, i am wondering, is this the general state of affairs for GUI programing, or is it just Java? I asked a bit on freenode irc, and it seems to be java, although i guess programing GUI using any widget toolkits is not gonna be a walk in the park.

I like to work on software projects that are mission critical, or backend engines, so i don't regard GUI apps that much important. Nevertheless, GUI, as its name implies, provides a graphical user interface, and is in fact a element most software needs. In particular, one of my hobby is programing geometric visualization. Imagine viewing and rotating a molecule structure in 3D. Such a software requires a GUI.

So, even knowing it's gonna be a pain, and at this point i'm gonna abandon Java's Swing again because it is intolerable, but i did half-heartedly looked into alternatives of GUI widgets, in part to acquaint myself what's out there, and maybe pave the road to learn a thing or two about how to actually use a widget toolkit to create a menu or button.

It seems to me, the most popular free GUI widget out there are:

Each has various language bindings. I think i might want to start to tinkle with PyGTK.

One thing interesting is that Cairo (graphics) is a recently developed library for drawing vector graphics, and recent version of GTK+ uses it.

The following apps i'm familiar with uses Qt: KDE (linux desktop), Linux version of Mathematica, Google Earth, Opera web browser, Skype, TeamSpeak.

Addendum. wxWidgets is a widget toolkit for creating graphical user interfaces (GUIs) for cross-platform applications. Audacity uses wxWidgets.

3D Programing Pain

Ok, that's about the GUI bit. But what about geometry visualization programing bit? The answer, is pretty much OpenGL (Mesa 3D), Direct3D.

Direct3D is Windows only. Since my professional expertise all lies in unix, and basically don't know much about Windows's technologies, so Direct3D is out for me.

Now, i have read about OpenGL a lot since 1994… but basically it is more low-level pain, perhaps a order of magnitude more painful than doing Java Swing. However, if you really want to get down to creating a geometry visualization software that is good quality (namely, fast), OpenGL or similar is a inevitability. (the alternative, of doing projections yourself and paint them to screen, is hackish and way slower)

Given my problem and persistent infatuation with visualization of geometry, i think going down getting familiar with OpenGL stuff is necessary, or strongly advisable. So, i started to read many articles on Wikipedia related to computer graphics, in particular the low level stuff. Here's some random articles or terms i'm learning or read.

Graphics pipeline. This is the most important concept. Basically, a 3D scene is passed to the graphics card, and processed in various stages, to produce a 2D bitmap for the screen.

Here are some general important concepts.

Some concepts at the bitmap stage.

3D Engines

… it seems to me that there are no high-level graphics engines. Fahrenheit graphics API and QuickDraw3D are supposed to be the one but went nowhere.

Some of the free game engines:

This seems to be the best: O3D for my needs. It uses a highlevel lang JavaScript, so i don't have to worry about low-level graphics faak. It accesses GPU transparently, so i don't have to worry about it. It runs in browser, which is what i need for my visualization apps. And it is in the position to be standardized as web 3D tech. The downside is that this will be few years to come.

Some free physics engines:

Game Development

Here's some articles related to game development.