first merge
[sdlgit/SDL_perl.git] / test / OpenGL / tutorial / lesson06.pl
diff --git a/test/OpenGL/tutorial/lesson06.pl b/test/OpenGL/tutorial/lesson06.pl
new file mode 100644 (file)
index 0000000..3a55e51
--- /dev/null
@@ -0,0 +1,371 @@
+#!/usr/bin/perl -w
+# This code was created by Jeff Molofee '99
+# (ported to SDL by Sam Lantinga '2000)
+# (ported to Perl/SDL by Wayne Keenan '2000)
+#
+# If you've found this code useful, please let me know.
+#
+# Visit me at www.demonews.com/hosted/nehe 
+
+use strict;
+use Getopt::Long;
+use Data::Dumper;
+use Benchmark;
+
+use SDL;
+use SDL::App;
+use SDL::OpenGL;
+use SDL::Event;
+
+my $arg_screen_width =640;
+my $arg_screen_height=512;
+my $arg_fullscreen=0;
+my $delay = 3;
+
+GetOptions(
+          "width:i"        => \$arg_screen_width,
+          "height:i"       => \$arg_screen_height,
+          "fullscreen!"    => \$arg_fullscreen,
+          "delay:i"    => \$delay,
+
+         ) or die $!;
+
+############################################################
+
+my ($xrot, $yrot, $zrot) = (0,0,0);
+
+main();
+exit;
+
+
+sub main
+  {  
+   my $done=0;
+   
+   my $app = new SDL::App ( -title => "Jeff Molofee's GL Code Tutorial ... NeHe '99", 
+                           -icon => "Data/perl.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);
+
+
+   while ( not $done ) {
+
+    DrawGLScene();
+
+    $app->sync();
+   
+    for (1 .. 10) {
+       $event->pump;
+       $event->poll;
+       $app->delay($delay);
+    }
+    
+    
+    if ( $event->type == SDL_QUIT ) {
+     $done = 1;
+    }
+
+    if ( $event->type == SDL_KEYDOWN ) {
+     if ( $event->key_sym == SDLK_ESCAPE ) {
+      $done = 1;
+     }
+    }
+   }
+  }
+
+
+
+
+
+
+#########################################################################
+#Pretty much in original form, but 'Perlised' 
+
+
+
+
+sub InitGL
+  {
+   my ($Width, $Height) = @_;
+
+   glViewport(0, 0, $Width, $Height);
+
+   LoadGLTextures();                           # Load The Texture(s) 
+
+   glEnable(GL_TEXTURE_2D());                  # Enable Texture Mapping
+
+   glClearColor(0.0, 0.0, 1.0, 0.0);                           # This Will Clear The Background Color To Black
+   glClearDepth(1.0);                                          # Enables Clearing Of The Depth Buffer
+   glDepthFunc(GL_LESS);                                       # The Type Of Depth Test To Do
+   glEnable(GL_DEPTH_TEST);                                    # Enables Depth Testing
+   glShadeModel(GL_SMOOTH);                                    # Enables Smooth Color Shading
+   
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();                                           # Reset The Projection Matrix
+   
+   gluPerspective(45.0, $Width/$Height, 0.1, 100.0);           # Calculate The Aspect Ratio Of The Window
+   
+   glMatrixMode(GL_MODELVIEW);
+  }
+
+
+
+# The main drawing function.
+sub DrawGLScene
+  {
+   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);         # Clear The Screen And The Depth Buffer
+   glLoadIdentity();                                           # Reset The View
+   
+   glTranslate(0.0,0.0,-5.0);                                  # move 5 units into the screen.
+   
+   glRotate($xrot,1.0,0.0,0.0);                                # Rotate On The X Axis
+   glRotate($yrot,0.0,1.0,0.0);                                # Rotate On The Y Axis
+   glRotate($zrot,0.0,0.0,1.0);                                # Rotate On The Z Axis
+   
+   glBindTexture(GL_TEXTURE_2D, 1);   # choose the texture to use.
+   
+   glBegin(GL_QUADS);                                          # begin drawing a cube
+   
+   # Front Face (note that the texture's corners have to match the quad's corners)
+   glTexCoord(0.0, 0.0); glVertex(-1.0, -1.0,  1.0);   # Bottom Left Of The Texture and Quad
+   glTexCoord(1.0, 0.0); glVertex( 1.0, -1.0,  1.0);   # Bottom Right Of The Texture and Quad
+   glTexCoord(1.0, 1.0); glVertex( 1.0,  1.0,  1.0);   # Top Right Of The Texture and Quad
+   glTexCoord(0.0, 1.0); glVertex(-1.0,  1.0,  1.0);   # Top Left Of The Texture and Quad
+   
+   # Back Face
+   glTexCoord(1.0, 0.0); glVertex(-1.0, -1.0, -1.0);   # Bottom Right Of The Texture and Quad
+   glTexCoord(1.0, 1.0); glVertex(-1.0,  1.0, -1.0);   # Top Right Of The Texture and Quad
+   glTexCoord(0.0, 1.0); glVertex( 1.0,  1.0, -1.0);   # Top Left Of The Texture and Quad
+   glTexCoord(0.0, 0.0); glVertex( 1.0, -1.0, -1.0);   # Bottom Left Of The Texture and Quad
+   
+   # Top Face
+   glTexCoord(0.0, 1.0); glVertex(-1.0,  1.0, -1.0);   # Top Left Of The Texture and Quad
+   glTexCoord(0.0, 0.0); glVertex(-1.0,  1.0,  1.0);   # Bottom Left Of The Texture and Quad
+   glTexCoord(1.0, 0.0); glVertex( 1.0,  1.0,  1.0);   # Bottom Right Of The Texture and Quad
+   glTexCoord(1.0, 1.0); glVertex( 1.0,  1.0, -1.0);   # Top Right Of The Texture and Quad
+   
+   # Bottom Face       
+   glTexCoord(1.0, 1.0); glVertex(-1.0, -1.0, -1.0);   # Top Right Of The Texture and Quad
+   glTexCoord(0.0, 1.0); glVertex( 1.0, -1.0, -1.0);   # Top Left Of The Texture and Quad
+   glTexCoord(0.0, 0.0); glVertex( 1.0, -1.0,  1.0);   # Bottom Left Of The Texture and Quad
+   glTexCoord(1.0, 0.0); glVertex(-1.0, -1.0,  1.0);   # Bottom Right Of The Texture and Quad
+   
+   # Right face
+   glTexCoord(1.0, 0.0); glVertex( 1.0, -1.0, -1.0);   # Bottom Right Of The Texture and Quad
+   glTexCoord(1.0, 1.0); glVertex( 1.0,  1.0, -1.0);   # Top Right Of The Texture and Quad
+   glTexCoord(0.0, 1.0); glVertex( 1.0,  1.0,  1.0);   # Top Left Of The Texture and Quad
+   glTexCoord(0.0, 0.0); glVertex( 1.0, -1.0,  1.0);   # Bottom Left Of The Texture and Quad
+   
+   # Left Face
+   glTexCoord(0.0, 0.0); glVertex(-1.0, -1.0, -1.0);   # Bottom Left Of The Texture and Quad
+   glTexCoord(1.0, 0.0); glVertex(-1.0, -1.0,  1.0);   # Bottom Right Of The Texture and Quad
+   glTexCoord(1.0, 1.0); glVertex(-1.0,  1.0,  1.0);   # Top Right Of The Texture and Quad
+   glTexCoord(0.0, 1.0); glVertex(-1.0,  1.0, -1.0);   # Top Left Of The Texture and Quad
+   
+   glEnd();                                                    # done with the polygon.
+   
+   $xrot+=15.0;                                                        # X Axis Rotation       
+   $yrot+=15.0;                                                        # Y Axis Rotation
+   $zrot+=15.0;                                                        # Z Axis Rotation
+
+   
+  }
+
+#my $image1,$a;  #this can cause a segfault in LoadGLTextures/glTexImage2D   !!!
+
+
+sub LoadGLTextures
+  {
+    # Load Texture
+
+   #uncomment this for a different method of loading:
+   #my $img_data  = read_gfx_file(FILENAME=>"../../ScrollerDemos/backdrop2.h");
+   #my $pixel_ptr = $img_data->{PIXEL_PTR};
+   #my $pic_info  = $img_data->{INFO};
+   #my $width     = $pic_info->{WIDTH};
+   #my $height    = $pic_info->{HEIGHT};
+
+    
+   #if you uncomment the bit above, comment this out:
+   #-snip-
+   my $surface=create_SDL_surface_from_file("Data/crate.png");
+   my $width=$surface->width();
+   my $height=$surface->height();
+   my $pitch = $surface->pitch();
+   my $bytespp=  $surface->bytes_per_pixel();
+   my $size=$pitch*$height;
+   my $pixels = $surface->pixels();
+
+   # Create Texture    
+   my $textures = glGenTextures(1);                #name texture
+       die "Could not genereate textures" unless $$textures[0];
+
+   glBindTexture(GL_TEXTURE_2D, $$textures[0]);   # 2d texture 
+   
+   
+   glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); # scale linearly when image bigger than texture
+   glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); # scale linearly when image smalled than texture
+  
+   glTexImage2D(GL_TEXTURE_2D(), 
+                  0,                      #level (0 normal, heighr is form mip-mapping)
+                  GL_RGB(),                      #internal format (3=GL_RGB)
+                  $width,$height,
+                  0,                      # border 
+                  GL_RGB(),                 #format RGB color data
+                 GL_UNSIGNED_BYTE(),       #unsigned bye data
+                 $pixels);            #ptr to texture data
+
+    die "Problem setting up 2d Texture (dimensions not a power of 2?)):".glErrorString(glGetError())."\n" if glGetError();
+
+  }
+
+sub create_SDL_surface_from_file
+  {
+   my $filename=shift;
+   
+   my $surface = new SDL::Surface( -name  => $filename);
+   
+   return $surface;
+                              
+  }
+
+
+
+
+
+###################
+#alternat loading support:
+
+#keep ref counts up:
+my @sprite_c_heap =();
+my @sprite_area =();
+
+sub read_gfx_file
+  {
+   my %args=(
+            TYPE       => "GIMP_HEADER",
+            FILENAME  => undef,
+            @_,
+           );
+   
+   my $struct   = read_gimp_header_image($args{FILENAME}); 
+   my $size     = length $struct->{DATA};
+   my $c_array  = new OpenGL::Array  $size  , GL_UNSIGNED_BYTE;
+
+   # c_array is the main reason to do the following ref count trickster:
+   # (otherwise the OpenGL:Array goes out of scope and the memory (image) is ZEROed out (and invalidated) by the DESTROY method
+   push @sprite_c_heap,  $c_array;             
+   push @sprite_area,    $struct;
+
+   $c_array->assign_data(0, $struct->{DATA} );   #take a copy of the data
+   
+   return {
+          PIXEL_PTR   => $c_array->ptr(), #could return $c_array instead to kepe ref count alive
+          INFO        => $struct,
+         };
+
+   #that all needs modularising.....
+
+  }
+
+
+#nasty fixed to 3 byte RGB 
+sub read_gimp_header_image
+  {
+   my $file=shift;
+   my $cached_file="$file.cached-bin";
+
+   my ($width, $height,$pixel_format, $data)=(0,0,"RGB","");
+
+   #due to that fact that this aint the fastest code ever, we keep a cache.
+   if (-e $cached_file and (-C $file >= -C $cached_file))
+     {
+
+      print "Reading cached binary bitmap data :  $cached_file\n";
+      open (FH, "<$file.cached-bin") or die "Open: $!";
+      my $line="";
+      $width=<FH>;
+      $height=<FH>;
+      $pixel_format=<FH>;
+      chomp $width;
+      chomp $height;
+      chomp $pixel_format;  #but who cares? not here anyway!!!
+
+      #slurp in the rest of the file (its pixel data)
+      {
+       local $/;
+       undef $/;
+       
+       my @lines= <FH>;
+       $data=join '', @lines;
+      }
+      
+      close (FH);
+     }
+   else                 # there is no cached file, or the cached file is out of date.
+     {
+      
+      open (FH, "<$file") or die "Open: $!";
+
+      my @data=();
+      my @pixel=();
+      while (defined (my $line=<FH>))
+       {
+        $width =$1 if ($line =~ /width\s*=\s*(\d+)/);
+        $height=$1 if ($line =~ /height\s*=\s*(\d+)/);
+        if ($line =~ /^\s+\"(.+)\"$/g)
+          {
+           my $c=$1;
+           $c =~ s/\\(.)/$1/g;                                 #remove meta guard
+           $c =~ 
+             s/
+               \G
+                 (.)(.)(.)(.)
+                   /
+                     @data=(ord($1),ord($2),ord($3),ord($4));
+           
+           chr    (  (  (  ( $data[0] - 33) <<  2)       | (  ($data[1] - 33) >> 4) ) ). 
+             chr (  (  (  (  ( $data[1] - 33) & 0xF) << 4) | (  ($data[2] - 33) >> 2) ) ).
+               chr (  (  (  (  ( $data[2] - 33) & 0x3) << 6) | (  ($data[3] - 33)     ) ) ); 
+           /gex;      
+           
+           $data.=$c ;
+          }
+       }
+      
+      
+      close(FH);
+      
+      print "Writing cached binary bitmap data for:  $file as $cached_file\n";
+      
+      #create a binary cached copy
+      open (FH, ">$cached_file") or die "Open: $!";
+      binmode FH;  #we might have to put up with weak OSes.
+      print FH  "$width\n$height\n$pixel_format\n$data";
+
+      close(FH);
+     }
+   
+
+
+
+   return {
+          WIDTH  => $width,
+          HEIGHT => $height,
+          FORMAT => $pixel_format,
+          DATA   => $data
+         };
+  }
+
+