--- /dev/null
+#!/usr/bin/perl
+# This code was created by Jeff Molofee '99
+# (ported to SDL by Sam Lantinga '2000)
+# (ported to Linux/SDL by Ti Leggett '01)
+
+# Lesson18 adapted by JusTiCe8 @2007 from others lesson and
+# ported to new Perl SDL, comments stripped (see Nehe lessons)
+
+# If you've found this code useful, please let me know.
+
+# Visit Jeff at http://nehe.gamedev.net/
+
+# or for port-specific comments, questions, bugreports etc.
+# email to leggett@eecs.tulane.edu (C/SDL)
+# or justice8@wanadoo.fr (SDL-Perl)
+
+use strict;
+use Getopt::Long;
+
+use SDL::Constants;
+use SDL::App;
+use SDL::OpenGL::Constants;
+use SDL::OpenGL;
+use SDL::Event;
+use SDL::Cursor;
+
+use constant NUM_TEXTURES => 3;
+
+my $arg_screen_width = 640;
+my $arg_screen_height = 480;
+my $arg_fullscreen = 0;
+my $delay = 5;
+
+my $light = 0;
+
+my ($part1, $part2);
+my ($p1, $p2) = (0, 1);
+
+my ($xrot, $yrot, $xspeed, $yspeed);
+my $z = -5.0;
+
+my $LightAmbient = [ 0.5, 0.5, 0.5, 1.0 ];
+my $LightDiffuse = [ 1.0, 1.0, 1.0, 1.0 ];
+my $LightPosition = [ 0.0, 0.0, 2.0, 1.0 ];
+
+my $quadratic;
+my $object = 5;
+my $filter = 1;
+
+# this flag is used to limit key strokes event
+my $pressed = 0;
+
+GetOptions
+ (
+ "width:i" => \$arg_screen_width,
+ "height:i" => \$arg_screen_height,
+ "fullscreen!" => \$arg_fullscreen,
+ "delay:i" => \$delay,
+ )
+ or die $!;
+
+main();
+exit;
+
+sub main
+{
+ my $done = 0;
+ my $fps = 0.0;
+ my $frames_drawn = 0;
+
+ my $app = new SDL::App
+ (
+ -title => "Jeff Molofee's lesson18: Quadratic",
+ -icon => "icon.png",
+ -width => $arg_screen_width,
+ -height => $arg_screen_height,
+ -opengl => 1,
+ );
+
+ $app->fullscreen if ($arg_fullscreen);
+
+ SDL::ShowCursor (0);
+
+ my $event = new SDL::Event;
+ $event->set (SDL_SYSWMEVENT (), SDL_IGNORE ());
+
+ InitGL ($arg_screen_width, $arg_screen_height);
+
+ my $prev_ticks = $app->ticks ();
+ my $fps_counter = 0.0;
+
+ while ( !$done )
+ {
+ DrawGLScene ();
+
+ $app->sync ();
+ $app->delay ($delay) if ($delay > 0);
+ $frames_drawn++;
+
+ my $ticks_now = $app->ticks ();
+ $fps_counter += $ticks_now - $prev_ticks;
+ $prev_ticks = $ticks_now;
+
+ if( $fps_counter >= 5000.0)
+ {
+ $fps = $frames_drawn / ($fps_counter / 1000.0);
+ printf("%d frames in %.2f seconds = %.3f FPS\n", $frames_drawn, $fps_counter / 1000.0, $fps);
+ $frames_drawn = 0;
+ $fps_counter = 0.0;
+ }
+
+ $event->pump;
+ $event->poll;
+
+ $done = 1 if ($event->type == &SDL_QUIT );
+
+ if ($event->type == &SDL_KEYDOWN )
+ {
+ $done = 1 if ($event->key_sym == &SDLK_ESCAPE );
+
+ if ($event->key_sym == &SDLK_f and !$pressed)
+ {
+ $filter = 1 + $filter % 3;
+ #print "Filter = $filter\n";
+ $pressed = 1;
+ }
+ elsif ($event->key_sym == &SDLK_l and !$pressed)
+ {
+ $light = !$light;
+ if (!$light)
+ {
+ glDisable ( &GL_LIGHTING );
+ } else {
+ glEnable ( &GL_LIGHTING );
+ }
+ $pressed = 1;
+ }
+ elsif ($event->key_sym == &SDLK_SPACE and !$pressed)
+ {
+ $object = ++$object % 6;
+ $pressed = 1;
+ }
+ elsif ($event->key_sym == &SDLK_PAGEUP)
+ {
+ $z -= 0.02;
+ }
+ elsif ($event->key_sym == &SDLK_PAGEDOWN)
+ {
+ $z += 0.02;
+ }
+ elsif ($event->key_sym == &SDLK_UP)
+ {
+ $xspeed -= 0.01;
+ }
+ elsif ($event->key_sym == &SDLK_DOWN)
+ {
+ $xspeed += 0.01;
+ }
+ elsif ($event->key_sym == &SDLK_RIGHT)
+ {
+ $yspeed += 0.01;
+ }
+ elsif ($event->key_sym == &SDLK_LEFT)
+ {
+ $yspeed -= 0.01;
+ }
+ }
+ elsif ($event->type == &SDL_KEYUP)
+ {
+ $pressed = 0;
+ }
+ }
+}
+
+
+sub InitGL
+{
+ my ($Width, $Height) = @_;
+ ($xrot, $yrot) = (0.0, 0.0);
+
+ glViewport (0, 0, $Width, $Height);
+
+ LoadGLTexture ();
+ glEnable (&GL_TEXTURE_2D);
+ glShadeModel (&GL_SMOOTH);
+
+ glClearColor (0.0, 0.0, 0.0, 0.0);
+ glClearDepth (1.0);
+
+ glEnable (&GL_DEPTH_TEST);
+ glDepthFunc (&GL_LESS); # GL_EQUAL as source tutorial don't work (?)
+ glHint ( &GL_PERSPECTIVE_CORRECTION_HINT, &GL_NICEST );
+
+ glLight ( &GL_LIGHT1, &GL_AMBIENT, @$LightAmbient );
+ glLight ( &GL_LIGHT1, &GL_DIFFUSE, @{$LightDiffuse} );
+ glLight ( &GL_LIGHT1, &GL_POSITION, @{$LightPosition} );
+
+ glEnable ( &GL_LIGHT1 );
+
+ $quadratic = gluNewQuadric ();
+ #gluQuadricNormals ( $quadratic, &GLU_SMOOTH );
+ gluQuadricTexture ( $quadratic, &GL_TRUE );
+
+ glMatrixMode (&GL_PROJECTION);
+ glLoadIdentity ();
+
+ gluPerspective (45.0, $Width/$Height, 0.1, 100.0);
+
+ glMatrixMode (&GL_MODELVIEW);
+}
+
+
+sub drawGLCube
+{
+ glBegin (&GL_QUADS);
+
+ glNormal ( 0.0, 0.0, 1.0);
+ glTexCoord (1.0, 0.0); glVertex (-1.0, -1.0, 1.0);
+ glTexCoord (0.0, 0.0); glVertex ( 1.0, -1.0, 1.0);
+ glTexCoord (0.0, 1.0); glVertex ( 1.0, 1.0, 1.0);
+ glTexCoord (1.0, 1.0); glVertex (-1.0, 1.0, 1.0);
+
+ glNormal ( 0.0, 0.0,-1.0);
+ glTexCoord (0.0, 0.0); glVertex (-1.0, -1.0, -1.0);
+ glTexCoord (0.0, 1.0); glVertex (-1.0, 1.0, -1.0);
+ glTexCoord (1.0, 1.0); glVertex ( 1.0, 1.0, -1.0);
+ glTexCoord (1.0, 0.0); glVertex ( 1.0, -1.0, -1.0);
+
+ glNormal ( 0.0, 1.0, 0.0);
+ glTexCoord( 1.0, 1.0); glVertex (-1.0, 1.0, -1.0);
+ glTexCoord (1.0, 0.0); glVertex (-1.0, 1.0, 1.0);
+ glTexCoord (0.0, 0.0); glVertex ( 1.0, 1.0, 1.0);
+ glTexCoord (0.0, 1.0); glVertex ( 1.0, 1.0, -1.0);
+
+ glNormal ( 0.0, -1.0, 0.0);
+ glTexCoord (0.0, 1.0); glVertex (-1.0, -1.0, -1.0);
+ glTexCoord (1.0, 1.0); glVertex ( 1.0, -1.0, -1.0);
+ glTexCoord (1.0, 0.0); glVertex ( 1.0, -1.0, 1.0);
+ glTexCoord (0.0, 0.0); glVertex (-1.0, -1.0, 1.0);
+
+ glNormal ( 1.0, 0.0, 0.0);
+ glTexCoord (0.0, 0.0); glVertex ( 1.0, -1.0, -1.0);
+ glTexCoord (0.0, 1.0); glVertex ( 1.0, 1.0, -1.0);
+ glTexCoord (1.0, 1.0); glVertex ( 1.0, 1.0, 1.0);
+ glTexCoord (1.0, 0.0); glVertex ( 1.0, -1.0, 1.0);
+
+ glNormal (-1.0, 0.0, 0.0);
+ glTexCoord (1.0, 0.0); glVertex (-1.0, -1.0, -1.0);
+ glTexCoord (0.0, 0.0); glVertex (-1.0, -1.0, 1.0);
+ glTexCoord (0.0, 1.0); glVertex (-1.0, 1.0, 1.0);
+ glTexCoord (1.0, 1.0); glVertex (-1.0, 1.0, -1.0);
+
+ glEnd();
+}
+
+
+sub DrawGLScene
+{
+ glClear(&GL_COLOR_BUFFER_BIT | &GL_DEPTH_BUFFER_BIT);
+ glLoadIdentity();
+
+ glTranslate ( 0.0, 0.0, $z);
+
+ glRotate ($xrot, 1.0, 0.0, 0.0);
+ glRotate ($yrot, 0.0, 1.0, 0.0);
+
+ glBindTexture(&GL_TEXTURE_2D, $filter);
+
+ if ($object == 0)
+ {
+ drawGLCube ();
+ }
+ elsif ($object == 1)
+ {
+ glTranslate ( 0.0, 0.0, -1.5 );
+ gluCylinder ( $quadratic, 1.0, 1.0, 3.0, 32, 32 );
+ }
+ elsif ($object == 2)
+ {
+ gluDisk ( $quadratic, 0.5, 1.5, 32, 32 );
+ }
+ elsif ($object == 3)
+ {
+ gluSphere ( $quadratic, 1.3, 32, 32 );
+ }
+ elsif ($object == 4)
+ {
+ glTranslate ( 0.0, 0.0, -1.5 );
+ gluCylinder ( $quadratic, 1.0, 0.0, 3.0, 32, 32 );
+ }
+ elsif ($object == 5)
+ {
+ $part1 += $p1;
+ $part2 += $p2;
+ if ( $part1 > 359 )
+ {
+ $p1 = 0;
+ $part1 = 0;
+ $p2 = 1;
+ $part2 = 0;
+ }
+ if ( $part2 > 359 )
+ {
+ $p1 = 1;
+ $p2 = 0;
+ }
+
+ gluPartialDisk ( $quadratic, 0.5, 1.5, 32, 32, $part1, $part2 - $part1 );
+ }
+
+ $xrot += $xspeed;
+ $yrot += $yspeed;
+}
+
+
+sub LoadGLTexture
+{
+ my ($pixels, $width, $height, $size) = ImageLoad ('data/wall.bmp');
+ #print "LoadGLTexture: w:$width h:$height s:$size\n";
+
+ my $textures = glGenTextures (NUM_TEXTURES);
+ unless ($$textures[0])
+ {
+ print "Could not generate textures\n";
+ return 0;
+ }
+
+ glBindTexture (&GL_TEXTURE_2D, 1); #$$textures[0]);
+
+ glTexImage2D
+ (
+ &GL_TEXTURE_2D,
+ 0,
+ 3,
+ $width, $height,
+ 0,
+ &GL_BGR,
+ &GL_UNSIGNED_BYTE,
+ $pixels
+ );
+
+ glTexParameter(&GL_TEXTURE_2D, &GL_TEXTURE_MAG_FILTER, &GL_NEAREST);
+ glTexParameter(&GL_TEXTURE_2D, &GL_TEXTURE_MIN_FILTER, &GL_NEAREST);
+
+
+ glBindTexture (&GL_TEXTURE_2D, 2);
+
+ glTexImage2D
+ (
+ &GL_TEXTURE_2D,
+ 0,
+ 3,
+ $width, $height,
+ 0,
+ &GL_BGR,
+ &GL_UNSIGNED_BYTE,
+ $pixels
+ );
+
+ glTexParameter (&GL_TEXTURE_2D, &GL_TEXTURE_MIN_FILTER, &GL_LINEAR);
+ glTexParameter (&GL_TEXTURE_2D, &GL_TEXTURE_MAG_FILTER, &GL_LINEAR);
+
+
+ glBindTexture (&GL_TEXTURE_2D, 3);
+
+ glTexParameter (&GL_TEXTURE_2D, &GL_TEXTURE_MIN_FILTER, &GL_LINEAR_MIPMAP_NEAREST);
+ glTexParameter (&GL_TEXTURE_2D, &GL_TEXTURE_MAG_FILTER, &GL_LINEAR);
+
+ gluBuild2DMipmaps
+ (
+ &GL_TEXTURE_2D,
+ 3,
+ $width, $height,
+ &GL_BGR,
+ &GL_UNSIGNED_BYTE,
+ $pixels
+ );
+
+ my $glerr = glGetError ();
+ if ($glerr)
+ {
+ print "Problem setting up 2d Texture (dimensions not a power of 2?)): ".gluErrorString ($glerr)."\n";
+ return 0;
+ }
+}
+
+
+sub ImageLoad
+{
+ my $filename = shift;
+ return unless (defined $filename and -e $filename);
+
+ #somthing needs to keep the ref count alive for objects which represents data in C space (they have no ref count):
+ my @ref = ();
+
+ #makes use of SDL: BMP loader.
+ my $surface = new SDL::Surface (-name => $filename);
+
+ my $width = $surface->width ();
+ my $height = $surface->height ();
+ my $bytespp = $surface->bytes_per_pixel ();
+ my $size = $width * $height * $bytespp;
+
+ return ($surface->pixels (), $width, $height, $size);
+
+
+ my $surface_pixels = $surface->pixels ();
+ my $surface_size = $width * $height * $surface->bytes_per_pixel ();
+ my $raw_pixels = reverse $surface_pixels;
+
+ #do a conversion (the pixel data is accessable as a simple string)
+ my $pixels = $raw_pixels;
+ my $pre_conv = $pixels;
+ my $new_pixels = '';
+
+ for (my $y = 0; $y< $height; $y++)
+ {
+ # calculate offset into the image (a string)
+ my $y_pos = $y * $width * $bytespp;
+
+ # extract 1 pixel row
+ my $row = substr ($pre_conv, $y_pos, $width*$bytespp);
+
+ # turn the BMP BGR order into OpenGL RGB order;
+ $row =~ s/\G(.)(.)(.)/$3$2$1/gms;
+ $new_pixels .= reverse $row;
+ }
+
+ $raw_pixels = $new_pixels;
+ push @ref, $raw_pixels, $surface;
+
+ # we could have created another SDL surface frm the '$raw_pixel's... oh well.
+ return ($raw_pixels, $width, $height, $size);
+}
+
+
+END
+{
+ gluDeleteQuadric ($quadratic);
+ $quadratic = undef;
+=item rem
+ use Devel::Peek;
+ print "Q=$quadratic\n";
+ mstat;
+ Dump ($quadratic, 5);
+ gluDeleteQuadric ($quadratic);
+ Dump ($quadratic, 5);
+ $quadratic = undef;
+ print "Q=$quadratic\n";
+ Dump ($quadratic, 5);
+=cut
+}