gleem: OpenGL Extremely Easy-to-use Manipulators Documentation

[Picture of Manipulators]

Last modified: 11/22/98. Current gleem version: 1.0

Introduction and Description

gleem is a small, self-contained C++ library of 3D widgets that support direct user interaction with a 3D scene. The user interfaces are roughly based on the manipulators in Silicon Graphics' Open Inventor; the names are borrowed from Inventor.

The currently implemented manipulators are:

The most recent version of gleem is available from

gleem uses GLUT and OpenGL for acquiring mouse events and performing rendering. However, all of the data structures for storing shapes and computing mouse pointer-object intersections are done within the library, not using the OpenGL pick mechanism. Therefore it should be fairly simple to port gleem to other graphics libraries such as Java3D.

gleem currently does not implement Inventor-style fields, field-to-field connections, reference counting, run-time type checking, instantiation by type ID, or any other of the basic mechanisms which made Inventor possible. It is implemented entirely using virtual functions; there is no casting down the hierarchy based on run-time type checks.

The most fundamental limitation of gleem is that, in the interest of portability, it has no notion of a scene graph. It defines what little such support it needs internally. All manipulators live conceptually in world coordinates. If you want to attach a manipulator to the end of a kinematic chain, for example, you will need to manually keep the manipulator in place as your application moves the links.

How to Incorporate gleem Into Your Programs

Compiling gleem

gleem was developed under SGI's Irix 6.5. The Makefile is currently set up for SGI's CC and include directories. Type "make" in the gleem subdirectory to build the library and tests. A precompiled version (built on a 6.5 Indy) is in lib/iris. You will need to set your LD_LIBRARY_PATH to, for example, /users/yourname/gleem-1.0/lib/iris before running any of the tests.

The sources should be quite portable and compilable with any recent C++ compiler. STL support is required and SGI's version of the STL is included in the distribution. By default gleem puts all of its datatypes into the namespace "gleem", but if your compiler doesn't support namespaces all of the macros gleem uses to this end are in Namespace.h. If you port gleem to another platform, please consider making a cross-platform Makefile for gmake and submitting your work; see the suggested projects. The "machtype" script in the top-level directory may be useful for this purpose.

Incorporating Manips

To use gleem's manipulators, you need to add the following to your OpenGL/GLUT application:

  1. A call to ManipManager::init() in main(). There must be an open window at this point if you want the ManipManager to install its callbacks. (To disable callback installation, call ManipManager::init(false).)
  2. If you choose not to allow the ManipManager to install mouse motion, passive motion, and mouse button callbacks (because you have already overridden them in your application), you need to call the appropriate static methods in ManipManager at the end of your callbacks.
  3. Regular calls to ManipManager::updateCameraParameters() with parameters of your viewing frustum (forward and up vectors, vertical FOV, image plane aspect ratio, horizontal and vertical size of window). gleem currently only handles frusta corresponding to symmetric truncated pyramids.
  4. A call to ManipManager::render() in your display callback.

You can then call methods such as getTranslation() and getRotation() on the above manipulator classes in, for example, its GLUT render callback, and feed those values elsewhere. You can also register a motion callback via Manip::addMotionCallback() which will be called each time the manipulator is moved.

See the sources Translate1Test.cpp, Translate2Test.cpp, and TestHandleBox.cpp for specific, small examples of instantiating manipulators.

Incorporating the Examiner Viewer

The ExaminerViewer class implements trackball-style rotation, translation, and dollying of the scene. To use it in conjunction with the ManipManager, you need to do the following:

  1. Instantiate an Examiner Viewer (i.e., ExaminerViewer viewer = new ExaminerViewer();). This creates a new window internally and overrides mouse and motion callbacks.
  2. Call ManipManager::init(false);. It isn't possible to re-install the ExaminerViewer's callbacks if they're overridden, so it's important not to let the ManipManager do so.
  3. Set up the ManipManager as a mouse and motion delegate for the ExaminerViewer.
  4. To get highlighting of manips to work, set up the ManipManager's passive motion callback manually.
  5. (Recommended) Give the ExaminerViewer a BSphereProvider so it can compute the bounding sphere of the scene, and call viewAll() before the first render. See TestExaminerViewer.cpp for an example of how you might compute a bounding sphere for a manipulator.
  6. Add a call to viewer->update(); before you begin drawing your geometry. This recomputes the ModelView and Projection matrices for the current rendering context. You should then be able to push matrices on top of the one loaded by the ExaminerViewer to effect a camera moving about the scene.

Multiple Window and Multi-Threading Support

gleem supports rendering manipulators in multiple windows. See ManipManager::windowCreated(), ManipManager::windowDestroyed(), ManipManager::addManipToWindow(), and ManipManager::removeManipFromWindow. By default, manipulators are rendered in the window which was current at the time of their instantiation (determined via glutGetWindow().) See TestMultiWin.cpp for an example of rendering the same manipulator into two windows.

gleem is not thread-safe. You should not attempt to instantiate or use gleem objects in more than one thread.

User Interface

Translate1Manip and Translate2Manip User Interface

The Translate1Manip and Translate2Manip are self-explanatory. Click and drag to cause motion along a line or in a plane.

HandleBoxManip User Interface

The HandleBoxManipulator contains a box with six faces. Clicking and dragging on any of these six faces causes translational motion in the plane parallel to the face.

This manipulator also contains six handles, each of which can be used to rotate the manipulator about two possible axes. The one chosen at the start of a drag motion is the one most parallel to the viewing direction. If you visualize the two perpendicular planes which go through the handle and three others, the one which is rotated about is the one which is facing the camera the most at the current time.

Scaling of the HandleBoxManip still needs to be implemented.

ExaminerViewer User Interface

The ExaminerViewer behaves similarly to Inventor's Examiner Viewer. It grabs all drag motions when the Alt key is depressed. The ExaminerViewer has a conceptual "focal point" which is always defined as being the focal distance directly in front of the viewer.

Drag motions with Alt key depressed:

Calling the viewAll() method re-positions (but does not re-orient) the ExaminerViewer so the bounding sphere given by the BSphereProvider is contained entirely within the viewing frustum. The focal distance is reset to be the distance between the camera and the center of the bounding sphere.

Developer Information

Class Hierarchy

gleem partitions its API into two sections, separate from the C++ access rules. Classes and access qualifiers prefaced with GLEEM_INTERNAL are not intended to be used by outside users, and have even fewer guarantees about interface stability than the public interfaces (which have none).

"Public" classes are in bold.

Manipulator-related classes

Application-level classes

Manipulator parts (visible and/or intersectable geometry)

Linear algebra classes

Other math-related classes

Per-Class Documentation

gleem contains a fair amount of documentation in the form of javadoc-style comments. I was not able to find a free document generator for C++ which could turn these into html; please let me know if you know of one. In the meantime, the headers contain all of the class-specific documentation.

Library Overview

Manipulators contain Manipulator Parts. The ManipPart hierarchy is divided into two sections, one containing triangle-based pieces of manipulators and one which contains grouping nodes (analogues to Group and Transform nodes). This is gleem's scene graph mechanism. A warning: shared instancing of "nodes" (ManipParts) in this scene graph is not allowed (since reference counting is not implemented). The ManipManager keeps track of all instantiated manipulators and handles the picking mechanism as well as rendering.

The Manip base class only implements a minimal interface; it is intended that you refer to manipulators through a pointer to the concrete type rather than the abstract Manip type. The simple manipulators (Translate1Manip, Translate2Manip) contain replaceGeometry() methods so you can customize the draggers with whatever geometry you like. It is not so simple to customize a more complex manipulator like the HandleBoxManip, so it contains no such method.

Each manipulator understands its constraints and implements its drag() method from scratch. Clearly there is some commonality between the Translate2Dragger and the translation functionality of the HandleBoxManip. However, this commonality has not been abstracted into a set of classes like Inventor's projectors. Instead there are a few geometrical classes (Line, Plane, PlaneUV) which encapsulate such functionality as ray casting and point projection, and the manipulators determine how to use this information based on what manipulator part was selected and the current configuration of the manipulator.

The linear algebra gleem uses is quite simple and should be accessible to anyone with anyone who has taken an undergraduate linear algebra course. I encourage you to experiment with more sophisticated algorithms for the drag mechanisms.

Recommended texts:

Suggestions for Further Development

I had originally intended to call gleem an acronym for "OpenGL Easily Extensible Manipulators", but decided that I shouldn't try to make that claim until other programmers had actually tried to do so. There is a lot of work still to be done on this library.

The one thing I strongly recommend against is attempting to turn gleem's internal scene graph (the ManipPart hierarchy) into a full scene graph library. The run-time support is not there, and the structure would need to be fully redesigned for this purpose. On the other hand, I think a free, portable, and high-performance scene graph library is a great idea.

Suggested projects:

Code contributions will be gladly accepted and incorporated into the "official" distribution. Or you can redistribute your modifications yourself; see below.

Licensing Terms

gleem is distributed under the GNU Library General Public License, version 2.0, or any later version. If you want to incorporate gleem into a commercial product, please contact me so we can discuss exceptions to the license's requirement that you distribute object files as well as gleem's (potentially modified) source code.

gleem includes a copy of SGI's STL implementation. Here is the copyright notice from this library:

 * Copyright (c) 1994
 * Hewlett-Packard Company
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  Hewlett-Packard Company makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 * Copyright (c) 1996
 * Silicon Graphics Computer Systems, Inc.
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  Silicon Graphics makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.

Frequently Asked Questions

Q: Why don't the manipulators show up in the right place in my application? (Or, why can't I drag them?)

A: gleem expects the following from the rendering state at the time you call ManipManager::render():

The latter is likely to be the problem. gleem expects to be able to render its manipulators in world coordinates, and the camera parameters you give the library must correspond to the current state of the ModelView and Projection matrices. See TestExaminerViewer.cpp for an example of how an application using gleem might be structured.

Acknowledgments, Thanks and Other Interesting Links

Version History

Kenneth B. Russell -
$Id: index.html,v 1.9 1998/12/11 04:47:31 kbrussel Exp $