BP

Previous

Next


use OpenGL;

#1 Image capture

This program shows how to get an image of an OpenGL window using ImageMagick.
The famous Utah teapot is used as an example.
For Windows users, the modules OpenGL, OpenGL::Image and Image::Magick are available in my ppm repositories:

 teapot  
#!/usr/local/bin/perl
#
# teapotgif.pl : make an animated gif image of a rotating teapot
# (c) 2013 jl_morel@bribes.org - http://http://bribes.org/perl
use strict;
use warnings;
use OpenGL qw/ :all /;
use OpenGL::Image;
use Image::Magick;

my $animatedgifname = "teapot.gif";
my $animatedgif     = Image::Magick->new();

my @light0_position    = ( 2.0,  8.0,  2.0,  0.0 );
my @light_diffuse      = ( 1.0,  1.0,  1.0,  1.0 );
my @light_ambient      = ( 0.15, 0.15, 0.15, 0.15 );
my @mat_amb_diff_color = ( 0.4,  0.2,  0.8,  1.0 );

#------ Initialization routine

sub init {
  glClearColor( 1, 1, 1, 1 );    # White background
  glShadeModel(GL_SMOOTH);       # Smooth shading
  glEnable(GL_DEPTH_TEST);       # Enable hidden surface removal
  glEnable(GL_MULTISAMPLE);      # Enable multisample antialiasing
  glEnable(GL_LIGHTING);         # Enable lighting
  glEnable(GL_LIGHT0);
  glLightfv_p( GL_LIGHT0, GL_POSITION, @light0_position );
  glLightfv_p( GL_LIGHT0, GL_DIFFUSE,  @light_diffuse );
  glLightfv_p( GL_LIGHT0, GL_AMBIENT,  @light_ambient );
  glMaterialfv_p( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, @mat_amb_diff_color );
  glEnable(GL_CLIP_PLANE0);      # One clip plane needed
}

#------ Draw the teapot

my $size = 3.5;                  # teapot size
my $spin = 0;                    # rotation angle

sub display {
  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

  glLoadIdentity();
  gluLookAt( 2.0, 4.0, 10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 );
  glPushMatrix();
  glRotatef( $spin, 0.0, 1.0, 0.0 );

  # The plane equation is 0x+0y+1z=0 with normal vector (0,0,1)
  glClipPlane_p( GL_CLIP_PLANE0, 0, 0, 1, 0 );
  glutSolidTeapot($size);

  # Same plane but with normal vector (0,0,-1)
  glClipPlane_p( GL_CLIP_PLANE0, 0, 0, -1, 0 );
  glutWireTeapot($size);

  glPopMatrix();
  glutSwapBuffers();
}

#------ GLUT Callback called when the window is resized

sub reshape {
  my ( $w, $h ) = @_;
  glViewport( 0, 0, $w, $h );
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective( 45.0, $h ? $w / $h : 0, 1.0, 20.0 );
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
}

#------ Routine for rotating the teapot

my $WaitUntil = 0;

sub spinDisplay {
  my $TimeNow = glutGet(GLUT_ELAPSED_TIME);
  if ( $TimeNow >= $WaitUntil ) {
    $spin += 1.0;
    if ( $spin > 360 ) {

      # 10/100ths of a second between images, loop indefinitely
      $animatedgif->Set( delay => 10, loop => 0 );
      $animatedgif->Write($animatedgifname);
      unlink "tmp.gif";
      exit;
    }
    if ( $spin % 5 == 0 ) {    # One capture every 5 degree
      IMCapture("tmp.gif");    # Save as gif image
      $animatedgif->Read("tmp.gif");
    }
    glutPostRedisplay();
    $WaitUntil = $TimeNow + 1000 / 25;    # 25 frames/s
  }
}

#------ Main

glutInit();
glutInitDisplayMode(
  GLUT_DOUBLE                             # Double buffering
    | GLUT_RGB                            # RGB color mode
    | GLUT_DEPTH                          # Hidden surface removal
    | GLUT_MULTISAMPLE                    # Multisample antialiasing
);
glutInitWindowSize( 420, 240 );
glutCreateWindow("Teapot");
init();
glutDisplayFunc( \&display );
glutReshapeFunc( \&reshape );
glutIdleFunc( \&spinDisplay );
glutMainLoop();

#------ Image capture function with ImageMagick
# Usage: IMCapture( $imgname [, $x, $y, $width, $height ] );
# $imgname is the image name with extension (.gif, .jpeg, .png ...)
# The optional part [ $x, $y, $width, $height ] defines  the dimensions
# of the rectangle to capture.
# If not supplied, the dimensions of the current window are used.

sub IMCapture {
  my $file = shift;
  my ( $x, $y, $width, $height ) = @_ == 4 ? @_ : glGetIntegerv_p(GL_VIEWPORT);
  my $img = new OpenGL::Image(
    engine => 'Magick',
    width  => $width,
    height => $height
  );
  my ( $def_fmt, $def_type ) = $img->Get( 'gl_format', 'gl_type' );
  glFinish();
  glReadPixels_c( $x, $y, $width, $height, $def_fmt, $def_type, $img->Ptr() );
  $img->Save($file);
}

The script as .txt for download: teapotgif.pl.txt

Back to Top


BP 2013 J-L Morel - Contact : jl_morel@bribes.org [Validation HTML 4.0!]