Chapter 3:  Input and Interaction

 

Input Devices

Most interesting graphical systems provide for user input.  The two standard input devices are a pointing device, usually implemented as a mouse, and a keyboard for input of ASCII characters.  The author of the book posits two uses of such input devices: measure (I call it “data”) and trigger.  The trigger device sends a signal to the computer and the measure device sends data, such as a string of characters, to the computer.

 

There a number of classes of devices worth a quick mention.  These include:

      String      allows for input of a string of characters
                     perhaps these characters are converted to numbers for later processing

      Locator   provides a position in logical coordinates to the graphical program

      Pick        returns the identity of the object selected

 

Input devices work in two basic modes.  In computer architecture, we refer to these modes as program-controlled input and interrupt-driven input.

 

Program-controlled input corresponds to what the book calls request-mode input and
sample-mode input.  The characteristic feature of these modes is that input is requested by a program in a standard manner, such as calls to standard input functions.

 

Interrupt-driven input corresponds to what the book calls event-mode input.  In this mode, the program responds to external events, such as clicks of the mouse.  A program written to respond to external events must have a mechanism for associating user-written methods with these events; i.e., what method should be invoked when a mouse button is clicked.  The approach used by OpenGL is called callback functions.  We shall say a lot more about callbacks when we discuss programming event-driven input.

 

Clients and Servers

The modern world of computer graphics is based on some sort of client-server model.  The reality is that there may be a number of users displaying and editing graphical data stored on a single database server.  Large systems are developed on the Microsoft three-tier model: client (display), middle (business rules), and server.

 

In this model, programs in the server layer are used only to store data.  In a graphics system the stored data is used to “persist” the graphical information so that it can be saved between editing sessions.  The business rule layer contains validity rules for the data.  Consider a design of a ship.  Some of the typical business rules would be:

      1)   Two independent pipes may not be so close that their outer walls overlap.
      2)   If a pump is placed on a deck, there must be a minimum clearance between that
            deck and the deck above to allow the pump to fit.

      3)   If a pump is placed on a deck, the deck may not be removed without providing
            another support for the pump.  Just because we can draw a pump hanging in the
            air with no supports does not make it possible in a real design.

 

In the three-tier model, software on the display (client) layer is used only to produce graphical images from the data as presented from the server layer and validated by the middle layer.  The client software might often include simple edit checks on the user input to avoid sending spurious or erroneous data to the middle layer.  For example, the client-layer software might specify a minimum distance for movement of a mouse before passing the mouse move to the middle layer.  This benefits users with hand tremors.

 

Display Lists

We also shall mention display lists only in passing.  The book describes a number of methods used to access the display lists directly.  Our studies will not focus on these methods, so we just mention the concept.  The origin of the display list is the desire to offload the task of displaying data from the computer that generates the data.

 

One essential feature of the display list is that it is not just a static picture but a set of descriptions from which number of pictures can be generated.  In any industrial graphic system, we demand the ability to display the view from a number of directions.  For example, we consider the following scene to be depicted graphically.

 

We have a cube 1 unit on a side centered one the X-axis at
X = 1, Y = 0, and Z = 0.

We also have a sphere with radius 0.7 centered on the
X-axis at X = 3, Y = 0, Z = 0.

 

The display list must contain all of this information.  Any two-dimensional representation of this scene must necessarily lose some of the information required for a full three-dimensional rendering.  For example, consider three possible views of this configuration.

 

As seen along the X axis, looking from the –X direction, the cube will obscure the sphere.  In this view, all information about the sphere is lost.  The main point here is that the display list must contain all the information required to generate any view.

 


Programming Event-Driven Input

The trick to developing event-driven software is the association of functions and procedures with the events so that the language run-time system can invoke the proper method whenever the event is detected.  In the early days of Windows programming, this was done by a Message Loop, essentially a case statement inside a loop forever statement.

 

OpenGL uses a set of functions to associate user-written functions with events.  In modern windowing systems, a display event is raised whenever a window opens or is resized.  User code that is to display to that window must use a predefined GLUT function to associate its display code with the display event.

 

In our sample code, the display function is
            void display ()

 

To cause the code in this function to be executed when a display event is raised, we use a standard GLUT function to associate the display function with the event.  Thus, the code
            glutDisplayFunc(display) ;

The specification of this function in the header GLUT.H is probably

            Void glutDisplayFunc (void (*func) (void))

Where func is the name of a function taking no arguments that will be called whenever the OpenGL window must be redisplayed.  Our function void display () fits the bill.

 

We associate a function with the mouse by use of the function glutMouseFunc, called as
            glutMouseFunc(mouse), where mouse is a user written function of the form
            void mouse (int button, int state, int x, int y)

 

Keyboard input is attached to the user program by the function glutKeyboardFunc, called as
            glutKeyboardFunc(keyboard), where keyboard is a user written function of the form
            void keyboard (unsigned char key, int x, int y)

 

The chapter has a number of other interesting topics, including animation.  We close our discussion of the chapter with a mention of double buffering.  In double buffering, we have two frame buffers, a front buffer (the one being displayed) and a back buffer (the one into which the program is drawing).  This allows a continuous display while not showing the sometimes time-consuming construction of the view.  A typical scenario involves two buffers, here called B1 and B2.  Note the start up period.  Nothing can be done until one buffer has been computed, in the first step of this example buffer B1 is being computed while buffer B2 remains empty.  Then B1 is displayed and the program begins filling B2.  At this point we have the true double buffering in effect.

 

            B1                                B2

            Compute                      Empty
            Display                         Compute
            Compute                      Display