[Prev][Next][Index][Thread]

Re: DUIM and OpenGL



"John Whittaker" <johncwhi@earthlink.net> writes:

> I would like to use Dylan--and specifically DUIM-- to learn about and
> experiment with OpenGL.  

I put together an OpenGL example that draws an OpenGL image on a DUIM
<drawing-pane>. The project for HD 1.2 and screenshot of it is at
http://www.double.co.nz/dylan. I tried to keep it to the bare minimum
required to display an OpenGL image. It's a port of a lisp example I
did for Corman Lisp way back which in turn came from an original C
sample.

I basically create a frame containing a single <drawing-pane>. This
pane has a display function that is used to display the opengl
image. The frame definition is:

  define frame <example1-frame> (<simple-frame>)
    slot %opengl-context = #f;
    virtual constant slot opengl-context;

    pane picture-pane (frame)
      make(<drawing-pane>, display-function: draw-picture-pane);

    layout (frame)
      vertically()
        frame.picture-pane;
      end;

    keyword title: = "OpenGL Example 1";
  end frame;

The opengl-context slot provides access to the HGLRC. This is created
on demand and stored in the actual %opengl-context slot:

  define method opengl-context( frame :: <example1-frame> ) 
    frame.%opengl-context |
      begin
        let hwnd = frame.picture-pane.window-handle; 
        let hdc = GetDC(hwnd);
        // Pretty much taken from the harlequin OpenGL example
        with-stack-structure (ppfd :: <PPIXELFORMATDESCRIPTOR>)
          [...snip...]
          SetPixelFormat(hdc, pixelformat, ppfd);
      end with-stack-structure;
      frame.%opengl-context := wglCreateContext(hdc);
      ReleaseDC(hdc, hwnd);  
      frame.%opengl-context;
    end;
  end method opengl-context;

I release various resources when the frame is unmapped:

  define method handle-event( frame :: <example1-frame>, 
      event :: <frame-unmapped-event> ) 
    => ()
      wglMakeCurrent($null-handle, $null-handle);
      wglDeleteContext( frame.opengl-context );
     frame.%opengl-context := #f;
  end method handle-event;

The paint method is quite simple:

  define method draw-picture-pane ( pane :: <drawing-pane>, 
      medium :: <medium>, region :: <region> ) => ()
    with-opengl-context( pane.sheet-frame.opengl-context, medium )
      let (width, height) = pane.sheet-size;
      glViewport(0, 0, width, height);
      glClear( $GL-COLOR-BUFFER-BIT );
      with-gl-begin( $GL-TRIANGLES )
        glColor3f( 1.0, 0.0, 0.0 );
        glVertex2i( 0, 1 );
        glColor3f(0.0, 1.0, 0.0 );
        glVertex2i( -1, -1 );
        glColor3f(0.0, 0.0, 1.0);
        glVertex2i( 1, -1 );
      end with-gl-begin;
      glFlush();
      Swapbuffers(medium.medium-drawable.get-dc);
    end;
  end method draw-picture-pane;

Where with-opengl-context and with-gl-begin and simple resource
handling macros which I won't put here but it is in the sample project
file.

The libraries and modules included win32-duim for window-handle and
get-dc and various other win-* for the Windows API functions. It
doesn't use much in the way of 'internal' stuff except for get-dc and
window-handle though.

That's pretty much all there was to it.

Hope it helps somewhat.

Chris.
-- 
http://www.double.co.nz/dylan



References: