/t_backcompat/OpenGL/tutorial/lesson18.pl

http://github.com/PerlGameDev/SDL · Perl · 411 lines · 301 code · 88 blank · 22 comment · 34 complexity · c181e6792f8bd1411d264a956cc8ce22 MD5 · raw file

  1. #!/usr/bin/perl
  2. # This code was created by Jeff Molofee '99
  3. # (ported to SDL by Sam Lantinga '2000)
  4. # (ported to Linux/SDL by Ti Leggett '01)
  5. # Lesson18 adapted by JusTiCe8 @2007 from others lesson and
  6. # ported to new Perl SDL, comments stripped (see Nehe lessons)
  7. # If you've found this code useful, please let me know.
  8. # Visit Jeff at http://nehe.gamedev.net/
  9. # or for port-specific comments, questions, bugreports etc.
  10. # email to leggett@eecs.tulane.edu (C/SDL)
  11. # or justice8@wanadoo.fr (SDL-Perl)
  12. use strict;
  13. use Getopt::Long;
  14. use SDL::Constants;
  15. use SDLx::App;
  16. use SDL::OpenGL::Constants;
  17. use SDL::OpenGL;
  18. use SDL::Event;
  19. use SDL::Cursor;
  20. use constant NUM_TEXTURES => 3;
  21. my $arg_screen_width = 640;
  22. my $arg_screen_height = 480;
  23. my $arg_fullscreen = 0;
  24. my $delay = 5;
  25. my $light = 0;
  26. my ( $part1, $part2 );
  27. my ( $p1, $p2 ) = ( 0, 1 );
  28. my ( $xrot, $yrot, $xspeed, $yspeed );
  29. my $z = -5.0;
  30. my $LightAmbient = [ 0.5, 0.5, 0.5, 1.0 ];
  31. my $LightDiffuse = [ 1.0, 1.0, 1.0, 1.0 ];
  32. my $LightPosition = [ 0.0, 0.0, 2.0, 1.0 ];
  33. my $quadratic;
  34. my $object = 5;
  35. my $filter = 1;
  36. # this flag is used to limit key strokes event
  37. my $pressed = 0;
  38. GetOptions(
  39. "width:i" => \$arg_screen_width,
  40. "height:i" => \$arg_screen_height,
  41. "fullscreen!" => \$arg_fullscreen,
  42. "delay:i" => \$delay,
  43. ) or die $!;
  44. main();
  45. exit;
  46. sub main {
  47. my $done = 0;
  48. my $fps = 0.0;
  49. my $frames_drawn = 0;
  50. my $app = SDLx::App->new(
  51. -title => "Jeff Molofee's lesson18: Quadratic",
  52. -icon => "icon.png",
  53. -width => $arg_screen_width,
  54. -height => $arg_screen_height,
  55. -opengl => 1,
  56. );
  57. $app->fullscreen if ($arg_fullscreen);
  58. SDL::ShowCursor(0);
  59. my $event = SDL::Event->new;
  60. $event->set( SDL_SYSWMEVENT(), SDL_IGNORE() );
  61. InitGL( $arg_screen_width, $arg_screen_height );
  62. my $prev_ticks = $app->ticks();
  63. my $fps_counter = 0.0;
  64. while ( !$done ) {
  65. DrawGLScene();
  66. $app->sync();
  67. $app->delay($delay) if ( $delay > 0 );
  68. $frames_drawn++;
  69. my $ticks_now = $app->ticks();
  70. $fps_counter += $ticks_now - $prev_ticks;
  71. $prev_ticks = $ticks_now;
  72. if ( $fps_counter >= 5000.0 ) {
  73. $fps = $frames_drawn / ( $fps_counter / 1000.0 );
  74. printf(
  75. "%d frames in %.2f seconds = %.3f FPS\n",
  76. $frames_drawn, $fps_counter / 1000.0, $fps
  77. );
  78. $frames_drawn = 0;
  79. $fps_counter = 0.0;
  80. }
  81. $event->pump;
  82. $event->poll;
  83. $done = 1 if ( $event->type == &SDL_QUIT );
  84. if ( $event->type == &SDL_KEYDOWN ) {
  85. $done = 1 if ( $event->key_sym == &SDLK_ESCAPE );
  86. if ( $event->key_sym == &SDLK_f and !$pressed ) {
  87. $filter = 1 + $filter % 3;
  88. #print "Filter = $filter\n";
  89. $pressed = 1;
  90. } elsif ( $event->key_sym == &SDLK_l and !$pressed ) {
  91. $light = !$light;
  92. if ( !$light ) {
  93. glDisable(&GL_LIGHTING);
  94. } else {
  95. glEnable(&GL_LIGHTING);
  96. }
  97. $pressed = 1;
  98. } elsif ( $event->key_sym == &SDLK_SPACE and !$pressed ) {
  99. $object = ++$object % 6;
  100. $pressed = 1;
  101. } elsif ( $event->key_sym == &SDLK_PAGEUP ) {
  102. $z -= 0.02;
  103. } elsif ( $event->key_sym == &SDLK_PAGEDOWN ) {
  104. $z += 0.02;
  105. } elsif ( $event->key_sym == &SDLK_UP ) {
  106. $xspeed -= 0.01;
  107. } elsif ( $event->key_sym == &SDLK_DOWN ) {
  108. $xspeed += 0.01;
  109. } elsif ( $event->key_sym == &SDLK_RIGHT ) {
  110. $yspeed += 0.01;
  111. } elsif ( $event->key_sym == &SDLK_LEFT ) {
  112. $yspeed -= 0.01;
  113. }
  114. } elsif ( $event->type == &SDL_KEYUP ) {
  115. $pressed = 0;
  116. }
  117. }
  118. }
  119. sub InitGL {
  120. my ( $Width, $Height ) = @_;
  121. ( $xrot, $yrot ) = ( 0.0, 0.0 );
  122. glViewport( 0, 0, $Width, $Height );
  123. LoadGLTexture();
  124. glEnable(&GL_TEXTURE_2D);
  125. glShadeModel(&GL_SMOOTH);
  126. glClearColor( 0.0, 0.0, 0.0, 0.0 );
  127. glClearDepth(1.0);
  128. glEnable(&GL_DEPTH_TEST);
  129. glDepthFunc(&GL_LESS); # GL_EQUAL as source tutorial don't work (?)
  130. glHint( &GL_PERSPECTIVE_CORRECTION_HINT, &GL_NICEST );
  131. glLight( &GL_LIGHT1, &GL_AMBIENT, @$LightAmbient );
  132. glLight( &GL_LIGHT1, &GL_DIFFUSE, @{$LightDiffuse} );
  133. glLight( &GL_LIGHT1, &GL_POSITION, @{$LightPosition} );
  134. glEnable(&GL_LIGHT1);
  135. $quadratic = gluNewQuadric();
  136. #gluQuadricNormals ( $quadratic, &GLU_SMOOTH );
  137. gluQuadricTexture( $quadratic, &GL_TRUE );
  138. glMatrixMode(&GL_PROJECTION);
  139. glLoadIdentity();
  140. gluPerspective( 45.0, $Width / $Height, 0.1, 100.0 );
  141. glMatrixMode(&GL_MODELVIEW);
  142. }
  143. sub drawGLCube {
  144. glBegin(&GL_QUADS);
  145. glNormal( 0.0, 0.0, 1.0 );
  146. glTexCoord( 1.0, 0.0 );
  147. glVertex( -1.0, -1.0, 1.0 );
  148. glTexCoord( 0.0, 0.0 );
  149. glVertex( 1.0, -1.0, 1.0 );
  150. glTexCoord( 0.0, 1.0 );
  151. glVertex( 1.0, 1.0, 1.0 );
  152. glTexCoord( 1.0, 1.0 );
  153. glVertex( -1.0, 1.0, 1.0 );
  154. glNormal( 0.0, 0.0, -1.0 );
  155. glTexCoord( 0.0, 0.0 );
  156. glVertex( -1.0, -1.0, -1.0 );
  157. glTexCoord( 0.0, 1.0 );
  158. glVertex( -1.0, 1.0, -1.0 );
  159. glTexCoord( 1.0, 1.0 );
  160. glVertex( 1.0, 1.0, -1.0 );
  161. glTexCoord( 1.0, 0.0 );
  162. glVertex( 1.0, -1.0, -1.0 );
  163. glNormal( 0.0, 1.0, 0.0 );
  164. glTexCoord( 1.0, 1.0 );
  165. glVertex( -1.0, 1.0, -1.0 );
  166. glTexCoord( 1.0, 0.0 );
  167. glVertex( -1.0, 1.0, 1.0 );
  168. glTexCoord( 0.0, 0.0 );
  169. glVertex( 1.0, 1.0, 1.0 );
  170. glTexCoord( 0.0, 1.0 );
  171. glVertex( 1.0, 1.0, -1.0 );
  172. glNormal( 0.0, -1.0, 0.0 );
  173. glTexCoord( 0.0, 1.0 );
  174. glVertex( -1.0, -1.0, -1.0 );
  175. glTexCoord( 1.0, 1.0 );
  176. glVertex( 1.0, -1.0, -1.0 );
  177. glTexCoord( 1.0, 0.0 );
  178. glVertex( 1.0, -1.0, 1.0 );
  179. glTexCoord( 0.0, 0.0 );
  180. glVertex( -1.0, -1.0, 1.0 );
  181. glNormal( 1.0, 0.0, 0.0 );
  182. glTexCoord( 0.0, 0.0 );
  183. glVertex( 1.0, -1.0, -1.0 );
  184. glTexCoord( 0.0, 1.0 );
  185. glVertex( 1.0, 1.0, -1.0 );
  186. glTexCoord( 1.0, 1.0 );
  187. glVertex( 1.0, 1.0, 1.0 );
  188. glTexCoord( 1.0, 0.0 );
  189. glVertex( 1.0, -1.0, 1.0 );
  190. glNormal( -1.0, 0.0, 0.0 );
  191. glTexCoord( 1.0, 0.0 );
  192. glVertex( -1.0, -1.0, -1.0 );
  193. glTexCoord( 0.0, 0.0 );
  194. glVertex( -1.0, -1.0, 1.0 );
  195. glTexCoord( 0.0, 1.0 );
  196. glVertex( -1.0, 1.0, 1.0 );
  197. glTexCoord( 1.0, 1.0 );
  198. glVertex( -1.0, 1.0, -1.0 );
  199. glEnd();
  200. }
  201. sub DrawGLScene {
  202. glClear( &GL_COLOR_BUFFER_BIT | &GL_DEPTH_BUFFER_BIT );
  203. glLoadIdentity();
  204. glTranslate( 0.0, 0.0, $z );
  205. glRotate( $xrot, 1.0, 0.0, 0.0 );
  206. glRotate( $yrot, 0.0, 1.0, 0.0 );
  207. glBindTexture( &GL_TEXTURE_2D, $filter );
  208. if ( $object == 0 ) {
  209. drawGLCube();
  210. } elsif ( $object == 1 ) {
  211. glTranslate( 0.0, 0.0, -1.5 );
  212. gluCylinder( $quadratic, 1.0, 1.0, 3.0, 32, 32 );
  213. } elsif ( $object == 2 ) {
  214. gluDisk( $quadratic, 0.5, 1.5, 32, 32 );
  215. } elsif ( $object == 3 ) {
  216. gluSphere( $quadratic, 1.3, 32, 32 );
  217. } elsif ( $object == 4 ) {
  218. glTranslate( 0.0, 0.0, -1.5 );
  219. gluCylinder( $quadratic, 1.0, 0.0, 3.0, 32, 32 );
  220. } elsif ( $object == 5 ) {
  221. $part1 += $p1;
  222. $part2 += $p2;
  223. if ( $part1 > 359 ) {
  224. $p1 = 0;
  225. $part1 = 0;
  226. $p2 = 1;
  227. $part2 = 0;
  228. }
  229. if ( $part2 > 359 ) {
  230. $p1 = 1;
  231. $p2 = 0;
  232. }
  233. gluPartialDisk( $quadratic, 0.5, 1.5, 32, 32, $part1, $part2 - $part1 );
  234. }
  235. $xrot += $xspeed;
  236. $yrot += $yspeed;
  237. }
  238. sub LoadGLTexture {
  239. my ( $pixels, $width, $height, $size ) = ImageLoad('data/wall.bmp');
  240. #print "LoadGLTexture: w:$width h:$height s:$size\n";
  241. my $textures = glGenTextures(NUM_TEXTURES);
  242. unless ( $$textures[0] ) {
  243. print "Could not generate textures\n";
  244. return 0;
  245. }
  246. glBindTexture( &GL_TEXTURE_2D, 1 ); #$$textures[0]);
  247. glTexImage2D(
  248. &GL_TEXTURE_2D, 0, 3, $width, $height, 0, &GL_BGR,
  249. &GL_UNSIGNED_BYTE, $pixels
  250. );
  251. glTexParameter( &GL_TEXTURE_2D, &GL_TEXTURE_MAG_FILTER, &GL_NEAREST );
  252. glTexParameter( &GL_TEXTURE_2D, &GL_TEXTURE_MIN_FILTER, &GL_NEAREST );
  253. glBindTexture( &GL_TEXTURE_2D, 2 );
  254. glTexImage2D(
  255. &GL_TEXTURE_2D, 0, 3, $width, $height, 0, &GL_BGR,
  256. &GL_UNSIGNED_BYTE, $pixels
  257. );
  258. glTexParameter( &GL_TEXTURE_2D, &GL_TEXTURE_MIN_FILTER, &GL_LINEAR );
  259. glTexParameter( &GL_TEXTURE_2D, &GL_TEXTURE_MAG_FILTER, &GL_LINEAR );
  260. glBindTexture( &GL_TEXTURE_2D, 3 );
  261. glTexParameter(
  262. &GL_TEXTURE_2D, &GL_TEXTURE_MIN_FILTER,
  263. &GL_LINEAR_MIPMAP_NEAREST
  264. );
  265. glTexParameter( &GL_TEXTURE_2D, &GL_TEXTURE_MAG_FILTER, &GL_LINEAR );
  266. gluBuild2DMipmaps(
  267. &GL_TEXTURE_2D, 3, $width, $height, &GL_BGR,
  268. &GL_UNSIGNED_BYTE, $pixels
  269. );
  270. my $glerr = glGetError();
  271. if ($glerr) {
  272. print "Problem setting up 2d Texture (dimensions not a power of 2?)): " . gluErrorString($glerr) . "\n";
  273. return 0;
  274. }
  275. }
  276. sub ImageLoad {
  277. my $filename = shift;
  278. return unless ( defined $filename and -e $filename );
  279. #somthing needs to keep the ref count alive for objects which represents data in C space (they have no ref count):
  280. my @ref = ();
  281. #makes use of SDL: BMP loader.
  282. my $surface = SDL::Surface->new( -name => $filename );
  283. my $width = $surface->width();
  284. my $height = $surface->height();
  285. my $bytespp = $surface->bytes_per_pixel();
  286. my $size = $width * $height * $bytespp;
  287. return ( $surface->pixels(), $width, $height, $size );
  288. my $surface_pixels = $surface->pixels();
  289. my $surface_size = $width * $height * $surface->bytes_per_pixel();
  290. my $raw_pixels = reverse $surface_pixels;
  291. #do a conversion (the pixel data is accessable as a simple string)
  292. my $pixels = $raw_pixels;
  293. my $pre_conv = $pixels;
  294. my $new_pixels = '';
  295. for ( my $y = 0; $y < $height; $y++ ) {
  296. # calculate offset into the image (a string)
  297. my $y_pos = $y * $width * $bytespp;
  298. # extract 1 pixel row
  299. my $row = substr( $pre_conv, $y_pos, $width * $bytespp );
  300. # turn the BMP BGR order into OpenGL RGB order;
  301. $row =~ s/\G(.)(.)(.)/$3$2$1/gms;
  302. $new_pixels .= reverse $row;
  303. }
  304. $raw_pixels = $new_pixels;
  305. push @ref, $raw_pixels, $surface;
  306. # we could have created another SDL surface frm the '$raw_pixel's... oh well.
  307. return ( $raw_pixels, $width, $height, $size );
  308. }
  309. END {
  310. gluDeleteQuadric($quadratic);
  311. $quadratic = undef;
  312. =item rem
  313. use Devel::Peek;
  314. print "Q=$quadratic\n";
  315. mstat;
  316. Dump ($quadratic, 5);
  317. gluDeleteQuadric ($quadratic);
  318. Dump ($quadratic, 5);
  319. $quadratic = undef;
  320. print "Q=$quadratic\n";
  321. Dump ($quadratic, 5);
  322. =cut
  323. }