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