Call-backs and initialisation

This next sample program is considerably more advanced. It uses double.c and Listing 1.3 from the Red Book. It illustrates the use of the mouse and various call-back functions. We will convert it to ClearWin+.

 1 #include "glos.h"
 2 
 3 #include <GL/gl.h>
 4 #include <GL/glu.h>
 5 #include <GL/glaux.h>
 6 
 7 void myinit(void);
 8 void CALLBACK spinDisplay (void);
 9 void CALLBACK startIdleFunc (AUX_EVENTREC *event);
10 void CALLBACK stopIdleFunc (AUX_EVENTREC *event);
11 void CALLBACK myReshape(GLsizei w, GLsizei h);
12 void CALLBACK display(void);
13 
14 static GLfloat spin = 0.0;
15 
16 void CALLBACK display(void)
17 {
18 glClear (GL_COLOR_BUFFER_BIT);
19 
20 glPushMatrix ();
21 glRotatef (spin, 0.0, 0.0, 1.0);
22 glRectf (-25.0, -25.0, 25.0, 25.0);
23 glPopMatrix ();
24 
25 glFlush();
26 auxSwapBuffers();
27 }
28 
29 void CALLBACK spinDisplay (void)
30 {
31 spin = spin + 2.0;
32 if (spin > 360.0)
33 spin = spin - 360.0;
34 display();
35 }
36 
37 void CALLBACK startIdleFunc (AUX_EVENTREC *event)
38 {
39 auxIdleFunc(spinDisplay);
40 }
41 
42 void CALLBACK stopIdleFunc (AUX_EVENTREC *event)
43 {
44 auxIdleFunc(0);
45 }
46 
47 void myinit (void)
48 {
49 glClearColor (0.0, 0.0, 0.0, 1.0);
50 glColor3f (1.0, 1.0, 1.0);
51 glShadeModel (GL_FLAT);
52 }
53 
54 void CALLBACK myReshape(GLsizei w, GLsizei h)
55 {
56 if (!h) return;
57 glViewport(0, 0, w, h);
58 glMatrixMode(GL_PROJECTION);
59 glLoadIdentity();
50 if (w <= h) 
61 glOrtho (-50.0, 50.0, -50.0*(GLfloat)h/(GLfloat)w, 
62 50.0*(GLfloat)h/(GLfloat)w, -1.0, 1.0);
63 else 
64 glOrtho (-50.0*(GLfloat)w/(GLfloat)h, 
65 50.0*(GLfloat)w/(GLfloat)h, -50.0, 50.0, -1.0, 1.0);
66 glMatrixMode(GL_MODELVIEW);
67 glLoadIdentity ();
68 }
69 
60 /* Main Loop
71 * Open window with initial window size, title bar, 
72 * RGBA display mode, and handle input events.
73 */
74 int main(int argc, char** argv)
75 {
76 auxInitDisplayMode (AUX_DOUBLE | AUX_RGB);
77 auxInitPosition (0, 0, 500, 500);
78 auxInitWindow ("Double Buffering");
79 myinit ();
70 auxReshapeFunc (myReshape);
81 auxIdleFunc (spinDisplay);
82 auxMouseFunc (AUX_LEFTBUTTON, AUX_MOUSEDOWN, startIdleFunc);
83 auxMouseFunc (AUX_RIGHTBUTTON, AUX_MOUSEDOWN, stopIdleFunc);
84 auxMainLoop(display);
85 return(0);
86 }

The converted program double.for is presented below. Note the use of common blocks rather than C global variables.

Lines 76 to 78 in the Red Book sample have been replaced by a few ClearWin+ calls at lines 109 to 111. %og (OpenGL Graphics Region) has been replaced by %^og indicating that a call-back function, opengl_proc, has been provided to handle messages. The use of %pv (Pivot) means that RESIZE messages are sent to the call-back.

Mouse messages are also sent to opengl_proc, as are the special SETUP and DIRTY messages. SETUP is sent only once, just after the window has been created and its arrival precedes that of RESIZE. DIRTY is sent when the window needs repainting, for example, after RESIZE or when the window is brought to the top after being partially obscured. If you take action on the DIRTY call-back, you will not need the static option on %og.

The Red Book variant of the program supplies several functions to handle events. These functions are still needed and perform the same task, but they are called directly in response to ClearWin+ messages sent to opengl_proc. The reshape function myReshape(x,y) is called in response to RESIZE. display is called in response to DIRTY. The mouse handling functions startIdleFunc and stopIdleFunc are called in response to MOUSE_LEFT_CLICK and MOUSE_RIGHT_CLICK. These are registered as call-backs with GLAUX at lines 70 and 82-83.

In the Red Book example, the initialising call to myinit at line 79 (just after the window has been created) is handled by ClearWin+ as a message sent to opengl_proc. This message is SETUP and is always sent before the first RESIZE message. The GLAUX idle function has no direct ClearWin+ equivalent. Instead, %lw is used in the winio@ call and program execution falls through into the following idle loop. The test for ctrl<0 at line 113 in the ClearWin+ example, allows the program to detect when the window has been closed so that program termination can proceed.

 1     SUBROUTINE display()
 2     INCLUDE <opengl.ins>,nolist
 3     REAL spin
 4     LOGICAL do_draw
 5     COMMON /double_com/do_draw,spin
 6 
 7     CALL glClear(GL_COLOR_BUFFER_BIT)
 8
 9     CALL glPushMatrix()
 10    CALL glRotatef(spin, 0.0, 0.0, 1.0)
 11    CALL glRectf(-25.0, -25.0, 25.0, 25.0)
 12    CALL glPopMatrix()
 13
 14    CALL glFlush()
 15    CALL swap_opengl_buffers()
 16    END
 17
 18     SUBROUTINE spinDisplay()
 19     INCLUDE <clearwin.ins>,nolist
 20     REAL spin
 21     LOGICAL do_draw
 22     COMMON /DOUBLE_COM/do_draw,spin
 23
 24     IF(do_draw)THEN
 25       spin = spin + 2.0
 26       IF(spin.GT.360.0)THEN
 27         spin = spin - 360.0
 28       ENDIF
 29       CALL display()
 30     ENDIF
 31     CALL temporary_yield@()
 32     END
 33
 34     SUBROUTINE startIdleFunc ()
 35     REAL spin
 36     LOGICAL do_draw
 37     COMMON /DOUBLE_COM/do_draw,spin
 38     do_draw=.TRUE.
 39     END
 40
 41     SUBROUTINE stopIdleFunc ()
 42     REAL spin
 43     LOGICAL do_draw
 44     COMMON /double_com/do_draw,spin
 45     do_draw=.FALSE.
 46     END
 47
 48     SUBROUTINE myinit ()
 49     INCLUDE <opengl.ins>,nolist
 50     CALL glClearColor (0.0, 0.0, 0.0, 1.0)
 51     CALL glColor3f (1.0, 1.0, 1.0)
 52     CALL glShadeModel (GL_FLAT)
 53     END
 54
 55     SUBROUTINE myReshape(w, h)
 56     INCLUDE <opengl.ins>,nolist
 57     INTEGER w,h
 58     DOUBLE PRECISION aspect_ratio
 59     IF(h.NE.0) THEN
 60       aspect_ratio=REAL(w)/h
 61
 62       CALL glViewport(0, 0, w, h)
 63       CALL glMatrixMode(GL_PROJECTION)
 64       CALL glLoadIdentity()
 65       IF (w.LE.h) THEN 
 66         CALL glOrtho(-50d0, 50d0, -50d0/aspect_ratio, 
 67    &       50d0/aspect_ratio, -1d0, 1d0)
 68       ELSE
 69         CALL glOrtho(-50d0*aspect_ratio, 
 70    &       50d0*aspect_ratio, -50d0, 50d0, -1d0, 1d0)
 71       ENDIF
 72       CALL glMatrixMode(GL_MODELVIEW)
 73       CALL glLoadIdentity ()
 74       CALL display()
 75       ENDIF
 76     END
 77
 78
 79     INTEGER FUNCTION opengl_proc()
 80     INCLUDE <clearwin.ins>,nolist
 81     CHARACTER*256 reason
 82     INTEGER w,h
 83     REASON=clearwin_string@('CALLBACK_REASON')
 84     IF(reason.EQ.'SETUP')THEN
 85       CALL myinit()
 86     ELSE IF(reason.EQ.'RESIZE')THEN
 87       w=clearwin_info@('OPENGL_WIDTH')
 88       h=clearwin_info@('OPENGL_DEPTH')
 89       CALL myReshape(w,h)
 90     ELSE IF(reason.EQ.'MOUSE_LEFT_CLICK')THEN
 91       CALL startIdleFunc()
 92     ELSE IF(reason.EQ.'MOUSE_RIGHT_CLICK')THEN
 93       CALL stopIdleFunc()
 94     END IF
 95 
 96     opengl_proc=2
 97     END
 98
 99     PROGRAM double
100     INCLUDE <clearwin.ins>,nolist
101     INTEGER i
102     INTEGER opengl_proc,ctrl
103     EXTERNAL opengl_proc
104     REAL spin
105     LOGICAL do_draw
106     COMMON /double_com/do_draw,spin
107     DATA spin,do_draw/0.0,.TRUE./
108 
109     i=winio@('%es%ca[Double Buffering]&')
110     i=winio@('%sp%ww[no_border]%pv%^og[double]%lw',
111    &         0,0,500,500,opengl_proc,ctrl)
112
113     WHILE(ctrl.LT.0)DO
114       CALL spinDisplay()
115     ENDWHILE
116     END

This program follows the structure that will be used throughout this chapter, and your attention is drawn again to the use of opengl_proc to call the reshape, display, initialisation and mouse handling functions.

 

 

Basket
Empty
 
Copyright © 1999-2024 Silverfrost Limited