|
Fifth Annual Tcl/Tk Workshop, 1997
   
[Technical Program]
A Tk OpenGL widgetClaudio Esperança COPPE, Engenharia de Sistemas e Computação AbstractWe present TkOGL, a Tk widget that enables the creation and display of 3D graphics using the OpenGL API. Our approach features a reasonably complete Tcl binding to the core OpenGL functionality, as well as a set of extensions that implement a higher-level interface to many common utility functions such as those provided by the OpenGL utility library (GLU). 1. IntroductionOpenGL [1] is becoming a standard Application Program Interface (API) for writing portable 3D computer graphics programs. On the other hand, the Tk toolkit offers a portable and powerful environment for the development of graphical user interfaces. It is to be expected then, that the merging of both capabilities should appeal to a wide audience. In fact, many attempts to do exactly that have been reported. Among these, we cite the Tiger system [2] and the Togl widget [3]. For various reasons, however, these packages did not meet my expectations. For instance, Tiger mimics the OpenGL API almost exactly, which makes the creation of simple 3D graphics unnecessarily complicated due to the inexistence of higher-level constructs. On the other hand, Togl, while providing the means to open a window for displaying OpenGL graphics, does not include Tcl bindings for any of the OpenGL rendering functions, thus forcing the user to program in C or C++. Our primary purpose in writing the Tkogl widget was to enable both the experienced and novice users to generate and display 3D models in a concise manner. Moreover, the widget takes care of low-level tasks related to the embedding of OpenGL on a given window system, such as adjusting viewports to reflect window resize events and buffer swapping for double-buffered visuals. The package was initially developed on an IBM RS-6000 workstation running AIX v3.2.5 and tested both with "real" OpenGL and with a free implementation of the OpenGL API, namely, the Mesa 3-D graphics library [4]. It was later ported to PCs running Microsoft's OpenGL implementation under Windows95. Currently, the package is known to work with Tcl 7.5/Tk 4.1 and Tcl 7.6/Tk 4.2. The distribution contains source code and Makefiles for some popular architecture/operating system combinations. In order to facilitate its installation in PCs, a pre-compiled DLL (dynamically loadable library) is also provided. The TkOGL home page address can be found at [5]. 2. Design IssuesOpenGL [1] is a software interface to 3D graphics which was designed to provide optimum performance on client/server architectures. Thus, a typical application (client) consists of calls to OpenGL functions which are translated into messages that are sent to the graphics hardware (server), where they are interpreted and executed. Since it was designed to be portable to different architectures, the exact protocol involved in OpenGL messaging may vary. While this flexibilty is one of the strong points of OpenGL, in practice a usable OpenGL implementation must define several interface details in a non-portable manner. In particular, creating a window for displaying OpenGL graphics is non-trivial and eminently architecture-dependent. This task is further complicated when we consider that our aim is to embed such windows in frames managed by Tk. Some of the issues involved in this task are:
These issues, although important, are not addressed further in this paper since they are not of interest to the typical user. The curious reader will be able to find some solutions to these problems by perusing the source code included in the Tkogl distribution [5]. Another important aspect concerning the integration of OpenGL and Tcl/Tk is the design of an appropriate set of Tcl bindings. Ideally, we would like an OpenGL widget to provide an interface which is similar to other Tk widgets. For instance, the canvas widget might serve as a model, since it provides the funcionality for generating 2D drawings. Unfortunately, however, 3D graphics are substantially more involved, and the overall approach used by canvas (i.e., to provide a few graphical item types such as rectangles and ovals which can be created and configured) cannot be employed in quite the same manner. The rest of this paper describes our approach to this problem. 3. A Simple Application Using TkoglThe integration between OpenGL and Tk is achieved by a package called Tkogl, which in Unix-based installations is statically linked in the extended Tcl/Tk windowing shell called glwish. Under Windows95, the package can be dynamically loaded by executing a corresponding package require command. In any case, a Tcl script which uses the package should include the following line:
Once it is ascertained that the package is loaded, one or more windows can be created for displaying OpenGL graphics. Such windows can be created in a similar way to other Tk widgets by using the OGLwin command, which has the following format:
where each option can be one of the following:
Currently, OGLwin can only be used to create windows which will use the RGBA color model. By default, OGLwin creates a double-buffered RGB window with the biggest number of bitplanes supported by the current software/hardware environment. The configuration options described above can be used to allocate additional buffers, e.g., an accumulation or a stencil buffer. If the requested buffers cannot be allocated, then OGLwin fails, producing a standard Tcl error result. An OpenGL window is typically created for visualizing a series of graphical objects. In most window systems, the contents of the window must be redrawn every once in a while, for instance, when the window is resized or deiconified. Usually, quite a few OpenGL rendering commands must be executed in order to reproduce the contents of the window. Although we aim to be able to generate any OpenGL command from within a Tcl script, it would be very time-consuming to interpret a very long sequence of Tcl commands every time a given OpenGL window needed to be redrawn. Fortunately, OpenGL offers a display list capability, whereby several commands can be pre-compiled and stored in the display server, ready to be re-executed as needed. Thus, a sensible management of an OpenGL window (such as the one created by the OGLwin command) is to reserve a display list which will contain all rendering commands that are to be executed whenever the window needs to be redrawn. In this document, we refer to such a list as the main list. In addition to calling the main list whenever a redraw is needed, the widget issues glFlush command and takes care of swapping the front and back buffers (when a double-buffered visual is being used). The contents of the main display list can be redefined by means of the main widget command, which has the following format:
where
option is one of the OpenGL commands currently supported by the
package. These will be described later on. The program listing in Example 1 below shows a very minimal script that creates a window to display a triangle. The display produced by that program is shown in Figure 1. Example 1: A simple script to display a triangle. package require Tkogl OGLwin .gl pack .gl gl main -clear colorbuffer -begin triangles \ -vertex -1 -1 \ -vertex 0 1 \ -vertex 1 -1 \ -end Figure 1: Display produced by the script of Example 1
Notice that the script above relies on several variables of the OpenGL state machine having their initial default values. For instance, the default value of the Color state is white, while the the default value of the ClearColor state is black, which means that the triangle will be drawn in white over a black background. Instead of using the main display list mechanism for keeping the window updated, it is also possible set up a script to be executed every time an Expose event is caught by Tk. In this case, instead of using the main widget command to set up the main display list, the same OpenGL commands can be issued by means of the eval widget command, which has the following syntax: pathName eval? option ... option ? where pathName and option have the same meanings as in the main command. For instance, it is possible to rewrite our minimal script to catch Expose events directly. This is shown in Example 2 below. Example 2: Displays a diagonal line by catching Expose events and redrawing the picture with the eval widget command. package require Tkogl pack .gl bind .gl It should be noticed that the default display list mechanism is usually superior to catching events and redisplaying the picture. This is because in the former case all OpenGL commands are already stored in a display list in the server, while in the latter case, all commands must be reinterpreted and transmitted from the client to the server every time the window must be redrawn. 4. OpenGL option commandsMany OGLwin widget commands (e.g., eval, main) require a list of options that denote OpenGL commands. The overall format of such options is glCommandName ? arg ... arg ? where glCommandName is a Tcl string that denotes an equivalent OpenGLcommand. The string corresponding to a given OpenGL procedure is the name of that procedure stripped of its gl prefix and of eventual data type suffix. Mixed upper- and lowercase characters can be used. Thus, for instance, procedure glMatrixMode corresponds to option -matrixmode (other lower/uppercase combinations such as -MatrixMode are also acceptable), procedure glColor3f corresponds to option -color, and so on. arg is a Tcl string equivalent to an argument in the corresponding OpenGL command. The following rules are useful to determine how OpenGL procedure arguments are mapped into equivalent Tcl strings:
Most OpenGL procedures have equivalent option commands. In a few cases, the argument lists of an option command and its associated OpenGL procedure have slightly different argument lists, chiefly those that deal with textures and images. Also, some procedures of the OpenGL Utility Library (glu) were also implemented as option commands. The complete list of option commands can be found in the documentation included in the Tkogl distribution [5]. 5. OGLwin widget commandsAlthough most of OpenGL's capabilities could be exercised by using the eval and main widget commands, we felt that certain common tasks might be more easily programmed if a suitable set of additional commands were provided. For example, the OpenGL Utility Library (glu) provides several functions that can be used to render quadric surfaces such as spheres, cones and cylinders. These functions control many aspects of the rendering process, such as the dimensions of the surface, whether texture coordinates should be generated, etc. This functionality can be captured in a more natural way within Tcl scripts with a corresponding widget command corresponding to the surface type to be rendered. Consider for instance the sphere widget command described below: pathName sphere?-displaylist dlist ? ? -normals normals ? ? -drawstyle drawStyle ? ? -orientation orientation ? ? -texturetexture ? radius slices stacks Renders a sphere using the GLU facilities for quadrics (refer to the gluCylinder function). By default, the rendering is compiled into a new display list whose number is returned as the result of the widget command. If a display list number dlist is specified by means of the -displaylist option, then that list is used. As a special case, if dlist is specified as none, the rendering is performed immediately, and no display list is generated or overwritten. The remaining options correspond to rendering styles as implemented by functions gluQuadricNormals, gluQuadricDrawStyle, gluQuadricOrientation and gluQuadricTexture, respectively. The possible option values are strings derived from corresponding symbolic constants. Thus, for instance, -normals flat corresponds to calling gluQuadricNormals with an argument equal to GLU_FLAT. The sphere command encapsulates all the functionality of the glu library procedures for rendering spheres. This is illustrated in the script labeled "Example 3" below which renders a shaded, textured sphere (see Figure 2). Example 3: Displays a textured shaded sphere. package require Tkogl # Create a checkerboard image image create photo tmp -width 2 -height 2 image create photo img -width 64 -height 64 tmp put {{white red} {black white}} img copy tmp -zoom 4 4 -to 0 0 64 64 # Create an OpenGL window pack [OGLwin .gl] # Configure point of view and texture .gl eval \ -matrixmode projection \ -ortho -2 2 -2 2 -2 2 \ -matrixmode modelview \ -rotate 30 1 1 0 \ -enable lighting \ -enable light0 \ -enable depthtest \ -enable texture2d \ -texparameter texture2d \ -texturewraps repeat \ -texparameter texture2d \ -texturewrapt repeat \ -texparameter texture2d \ -texturemagfilter nearest \ -texparameter texture2d \ -textureminfilter nearest \ -texenv textureenv \ -textureenvmode modulate\ -teximage2d 0 0 img # Create sphere object set quadric [.gl sphere -texture yes \ -drawstyle fill -normals smooth 1.8 20 20] .gl main -clear colorbuffer depthbuffer\ -call $quadric Figure 2: Display produced by the script of Example 3.
Note in Example 3 that the texture image was created by means of Tk's photo extensions. The Tkogl package interacts with images created with Tk in order to provide a smooth integration with OpenGL capabilities. Thus, the argument list of OpenGL function glTexImage2d was slightly modified in the corresponding Tkogl option command -teximage2d so that an image name could be used instead of an array of bytes. The Tkogl package implements several widget commands that encapsulate capabilities usually accessed by means of the glu library such as the rendering of quadric and NURBS surfaces, polygon tesselation, etc. Additional widget commands are also included to implement other useful rendering and modeling extensions not supported by the glu library. For example, Tkogl includes the gencyl command, which supports the creation of generalized cylinders (i.e., objects obtained by sweeping a two-dimensional shape along a curve in 3D). Figure 3 depicts one of these objects obtained with a demo application included in the distribution. Figure 3: Generalized cylinder object obtained with a demo application.
6. Input EventsOne of the nicest features of Tk is the simple way user-input events can be handled by means of the bind command. The OpenGL standard, on the other hand, offers limited facilities for managing input. These facilities, however, were included in the Tkogl package and can be easily put into use within a Tcl script. For instance, one of the most bothersome difficulty lies in establishing the correspondence between window coordinates and world coordinates. The GLU library provides two functions - gluProject and gluUnProject - for exactly that purpose. While these functions require a long list of arguments which include the current viewport and transformation matrices, their Tkogl counterparts - the project and unproject widget commands - only require three arguments representing the three coordinate values of the point to be transformed. Example 4 below demonstrates the use of the unproject command in a program for drawing lines. Notice how points which are input by clicking the mouse button are captured with a bind command and passed into procedure newvertex which computes the corresponding world coordinates. A sample output of this program is shown in Figure 4. Example 4: A simple line drawing program. package require Tkogl pack [OGLwin .gl] proc newvertex { x y } { global vertices append vertices -vertex " [.gl unproject $x $y 0] " eval .gl main -clear colorbuffer\ -begin lines $vertices -end } .gl main -clear colorbuffer bind .gl Figure 4: Sample output of the script "Example 4".
Other OpenGL facilities for handling user input are similarly supported in Tkogl. In particular, object selection and "picking" can be handled in Tkogl through the use of the select command. This command takes care of allocating a hit buffer and processing the list of hit objects, returning a single Tcl list which can then be easily parsed within the script. 7. ConclusionsWe described our implementation of a Tk widget for generating and displaying
3D graphics through the use of the OpenGL API. Our approach, in contrast
with similar ports of OpenGL to the Tcl/Tk environment, combines the accessibility
of most OpenGL functions through widget commands and options with a repertoire
of extensions that enable users to model several objects with compact Tcl
scripts. References
|
This paper was originally published in the
Proceedings of the Fifth Annual Tcl/Tk Workshop 1997,
July 14-17, 1997,
Boston, Massachusetts, USA
Last changed: 16 April 2002 aw |
|