Silverfrost Logo About Us | Contact Us
 

Animation and multiple windows

OpenGL achieves animation by using two buffers, the front and the back buffer. When this, so called, double buffering is enabled, drawing (or rendering in OpenGL terminology) is directed to the back buffer. When the image is complete, you transfer it to the front buffer, or display, by calling swap_opengl_buffers@. This ClearWin+ routine merely remembers the current OpenGL context and so saves the programmer effort. When the back buffer is transferred to the display, it is supposed to be no longer valid so two successive swap buffer calls should produce garbage on the display. Although this does not seem to happen under Win32, the retention of the buffer should not be relied upon, as it might not be retained on other platforms.

The program below is not a Red Book sample. It illustrates the use of multiple windows, independently animated. This is something not possible using GLAUX.

The use of multiple OpenGL windows requires that you know the device context and rendering context for each of the windows. Changing from one window to another requires that you swap both the device context and the rendering context. Therefore, you must "enquire" them and store them away. These enquiry and swapping functions (together with some functions) are known as the WGL set. They do not form part of OpenGL, but are essential to the Windows implementation of it. Documentation for these functions will be found in the Microsoft Developer Network help files. You can be sure that when opengl_proc is called, the expected device and rendering contexts are current.

The font is also set by means of a WGL call, wglUseFontOutlines. Note how, in the the program, a C type NULL pointer is simulated by CORE4(0). This function call will only be successful if the format code %fn is used in the definition of the parent window.

**********************************
*                                *
*     Animation using OpenGL     *
*                                *
**********************************

     SUBROUTINE display()
     INCLUDE <opengl.ins>,nolist
     INCLUDE <clearwin.ins>,nolist
     INCLUDE 'danimate.ins'

     CALL glClear (OR(GL_COLOR_BUFFER_BIT,GL_DEPTH_BUFFER_BIT))
     CALL glMatrixMode (GL_MODELVIEW)
     CALL glLoadIdentity()
     CALL glTranslated(0d0,0d0,-10d0)
     CALL glRotated(spin,1d0,0d0,0d0)
     CALL glCallList(101)
     CALL swap_opengl_buffers()
     CALL glFlush()
     END

     SUBROUTINE swapContexts(window)
     INTEGER window
     INCLUDE <opengl.ins>
     INCLUDE 'danimate.ins'
     CALL wglMakeCurrent(devicecontext(window),
    &                    renderingcontext(window))
     END

     SUBROUTINE spinSlab(window)
     INTEGER window
     INCLUDE 'danimate.ins'
     do_draw(window)=.TRUE.
     END

     SUBROUTINE stopSlab(window)
     INTEGER window
     INCLUDE 'danimate.ins'
     do_draw(window)=.FALSE.
     END

     SUBROUTINE assemble_list
     INCLUDE <clearwin.ins>,nolist
     INCLUDE <opengl.ins>,nolist

     REAL*4 white_colour(4),grey_colour(4),dark_grey_colour(4)
     REAL*4 red_colour(4), yellow_colour(4), green_colour(4)
     REAL*4 blue_colour(4), purple_colour(4), cyan_colour(4)
     REAL*8 dimension,scale,d,fd,front,back
     INTEGER flags,k
     INTEGER hdc
     LOGICAL ok
     DATA white_colour/1.0,1.0,1.0,1.0/
     DATA grey_colour/0.5,0.5,0.5,1.0/
     DATA dark_grey_colour/0.3,0.3,0.3,1.0/
     DATA red_colour/1.0,0.0,0.0,1.0/
     DATA yellow_colour/1.0,1.0,0.0,1.0/
     DATA green_colour/0.0,1.0,0.0,1.0/
     DATA blue_colour/0.0,0.0,1.0,1.0/
     DATA purple_colour/1.0,0.0,1.0,1.0/
     DATA cyan_colour/0.0,1.0,1.0,1.0/
     DATA front,back/-0.01d0,-0.5d0/

     CALL glEnable(GL_DEPTH_TEST)
     hDC=clearwin_info@('OPENGL_DEVICE_CONTEXT')
     CALL glColor3f(1.0,1.0,1.0)

     ok=wglUseFontOutlines(hDC, 0, 255, 1000, 0.0, 0.1,
    &                     WGL_FONT_POLYGONS,core4(0))
     
     CALL glMatrixMode (GL_MODELVIEW)
     CALL glLoadIdentity()
     CALL glTranslated(0d0,0d0,-10d0)

c----Clear the color and depth buffers.

     CALL glClear (OR(GL_COLOR_BUFFER_BIT,GL_DEPTH_BUFFER_BIT))
     dimension=2.2d0
     scale=dimension*0.9d0
     CALL glDisable(GL_LIGHTING)

     CALL glNewList(101,GL_COMPILE)
c----Front face
     CALL glBegin(GL_POLYGON)
     CALL glColor3fv(blue_colour)
     CALL glVertex3d(-dimension,-dimension,front)
     CALL glVertex3d(-dimension, dimension,front)
     CALL glVertex3d( dimension, dimension,front)
     CALL glVertex3d( dimension,-dimension,front)
     CALL glEnd()
c----Back face                         
     CALL glBegin(GL_POLYGON)
     CALL glColor3fv(yellow_colour)
     CALL glVertex3d(-dimension,-dimension,back)
     CALL glVertex3d( dimension,-dimension,back)
     CALL glVertex3d( dimension, dimension,back)
     CALL glVertex3d(-dimension, dimension,back)
     CALL glEnd()
c----Top face
     CALL glBegin(GL_POLYGON)
     CALL glColor3fv(red_colour)
     CALL glVertex3d(-dimension, dimension,front)
     CALL glVertex3d(-dimension, dimension,back)
     CALL glVertex3d( dimension, dimension,back)
     CALL glVertex3d( dimension, dimension,front)
     CALL glEnd()
c----Bottom face
     CALL glBegin(GL_POLYGON)
     CALL glColor3fv(green_colour)
     CALL glVertex3d( dimension,-dimension,front)
     CALL glVertex3d( dimension,-dimension,back)
     CALL glVertex3d(-dimension,-dimension,back)
     CALL glVertex3d(-dimension,-dimension,front)
     CALL glEnd()

c----Draw graph

     CALL glBegin(GL_LINES)
     CALL glColor3fv(white_colour)
     CALL glVertex2d(-scale,0d0)
     CALL glVertex2d(scale,0d0)
     CALL glVertex2d(0d0,-scale)
     CALL glVertex2d(0d0,scale)
     k=-10
     WHILE(k .LE. 10) DO
       CALL glVertex2d((scale/10)*k,0.0d0)
       CALL glVertex2d((scale/10)*k,0.1d0)
       CALL glVertex2d(0.0d0,(scale/10)*k)
       CALL glVertex2d(0.1d0,(scale/10)*k)
       k=k+1
     ENDWHILE
     CALL glEnd()
     CALL glColor3fv(red_colour)
     CALL glBegin(GL_LINE_STRIP)
     d=-10d0
     WHILE(d .LT. 10d0)DO
       fd=5*(d/10)**3+3*(d/10)**2-d/10
       CALL glVertex2d(d*scale/10,fd*scale/10)
       d=d+0.05d0
     ENDWHILE
     CALL glEnd()
     CALL glColor3fv(green_colour)
     CALL glBegin(GL_LINE_STRIP)
     d=-10d0
     WHILE(d .LT. 10)DO
       fd=5*(d/10)**3+6*(d/10)**2-d/10
       CALL glVertex2d(d*scale/10,fd*scale/10)
       d=d+0.05d0
     ENDWHILE
     CALL glEnd()
     CALL glColor3fv(red_colour)
     CALL glListBase(1000)
     CALL glTranslated(0.15d0,scale*0.95,0d0)
     CALL glScaled(0.2d0,0.2d0,0.2d0)
     CALL glCallLists(5, GL_UNSIGNED_BYTE, '+10.0')
     CALL glEndList()
     END
    
     SUBROUTINE myinit()
     CALL assemble_list()
     END

     SUBROUTINE myreshape(w,h)
     INCLUDE <opengl.ins>,nolist
     INTEGER w
     INTEGER h
     DOUBLE PRECISION aspect_ratio
                     
     IF(h.NE.0)THEN
       aspect_ratio=dble(w)/h
       CALL glMatrixMode(GL_PROJECTION)
       CALL glLoadIdentity()
       CALL gluPerspective(30.0d0,aspect_ratio,1d0,15d0)
       CALL glViewport(0,0,w,h)
     ENDIF

     END

     INTEGER FUNCTION opengl_proc1()
     INCLUDE <clearwin.ins>,nolist
     INCLUDE <opengl.ins>,nolist
     INCLUDE 'danimate.ins',nolist
     INTEGER w,h
     CHARACTER*256 reason
     reason=clearwin_string@('CALLBACK_REASON')
     
     IF(reason.EQ.'SETUP')THEN
       CALL myinit()
     ELSEIF(reason.EQ.'RESIZE')THEN
       w=clearwin_info@('OPENGL_WIDTH')
       h=clearwin_info@('OPENGL_DEPTH')
       CALL myreshape(w,h)
     ELSEIF(reason.EQ.'DIRTY')THEN
       CALL display()
       window1_active=.true.
     ELSEIf(reason.EQ.'MOUSE_LEFT_CLICK')THEN
       CALL spinSlab(1)
     ELSEIF(reason.EQ.'MOUSE_RIGHT_CLICK')THEN
       CALL stopSlab(1)
     ENDIF

     opengl_proc1=2
     END

     INTEGER FUNCTION opengl_proc2()
     INCLUDE <clearwin.ins>,nolist
     INCLUDE <opengl.ins>,nolist
     INCLUDE 'danimate.ins'
     INTEGER w,h
     CHARACTER*256 reason
     reason=clearwin_string@('CALLBACK_REASON')
     
     IF(reason.EQ.'SETUP')THEN
       CALL myinit()
     ELSEIF(reason.EQ.'RESIZE')THEN
       w=clearwin_info@('OPENGL_WIDTH')
       h=clearwin_info@('OPENGL_DEPTH')
       CALL myreshape(w,h)
     ELSEIF(reason.EQ.'DIRTY')THEN
       CALL display()
       window2_active=.true.
     ELSEIF(reason.EQ.'MOUSE_LEFT_CLICK')THEN
       CALL spinSlab(2)
     ELSEIF(reason.EQ.'MOUSE_RIGHT_CLICK')THEN
       CALL stopSlab(2)
     ENDIF
     CALL temporary_yield@()
     opengl_proc2=2
     END

     PROGRAM Animate
     INCLUDE <opengl.ins>,nolist
     INCLUDE <clearwin.ins>,nolist
     DOUBLE PRECISION spin_array(2)
     INTEGER i,window1,window2
     INTEGER opengl_proc1, opengl_proc2
     EXTERNAL opengl_proc1,opengl_proc2
     INCLUDE 'danimate.ins'

     do_draw(1)=.true.
     do_draw(2)=.true.
     devicecontext(1)=0
     devicecontext(2)=0
     renderingcontext(1)=0
     renderingcontext(2)=0
     spin=0d0
     spin_array(1)=0d0
     spin_array(2)=0d0
     window1_active=.false.
     window2_active=.false.
                        
c----Create a couple of OpenGL Windows
c----Window 1
     i=winio@('%es%ca[Rotating Slab]&')
     i=winio@('%fn[Times New Roman]%ts&',3.0d0)
     i=winio@('%sp%ww[no_border]%pv%^og[double,depth16]%lw'.
    &         0,0,350,350,opengl_proc1,window1)

c----Get and save hDC and the Rendering Contexts

     devicecontext(1)=wglGetCurrentDC()
     renderingcontext(1)=wglGetCurrentContext()

c----Create a couple of OpenGL Windows
c----Window 2
     i=winio@('%es%ca[Rotating Slab]&')
     i=winio@('%fn[Times New Roman]%ts&',3.0d0)
     i=winio@('%sp%ww[no_border]%pv%^og[double,depth16]%lw',
    &         400,0,350,350,opengl_proc2,window2)

c----Get and save hDC and the Rendering Contexts

     devicecontext(2)=wglGetCurrentDC()
     renderingcontext(2)=wglGetCurrentContext()

     do_draw(1)=.true.
     do_draw(2)=.true.

     WHILE(window1.LT.0 .OR. window2.LT.0)DO
       IF(window1.LT.0)THEN
         IF(do_draw(1))THEN
           spin_array(1)=spin_array(1)+2d0
           spin=spin_array(1)
           CALL swapContexts(1)
           CALL display()
         ENDIF           
       ENDIF
       IF(window2.LT.0)THEN
         IF(do_draw(2))THEN
           spin_array(2)=spin_array(2)+2d0
           spin=spin_array(2)
           CALL swapContexts(2)
           CALL display()
         ENDIF                 
       ENDIF
       CALL temporary_yield@()
     ENDWHILE
     END

 

 

Copyright © 1999-2017 Silverfrost Limited