Commit | Line | Data |
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 | |
17 | use strict; |
18 | use Getopt::Long; |
19 | |
20 | use SDL::Constants; |
21 | use SDL::App; |
22 | use SDL::OpenGL::Constants; |
23 | use SDL::OpenGL; |
24 | use SDL::Event; |
25 | use SDL::Cursor; |
26 | |
27 | use constant NUM_TEXTURES => 3; |
28 | |
29 | my $arg_screen_width = 640; |
30 | my $arg_screen_height = 480; |
31 | my $arg_fullscreen = 0; |
32 | my $delay = 5; |
33 | |
34 | my $light = 0; |
35 | |
36 | my ($part1, $part2); |
37 | my ($p1, $p2) = (0, 1); |
38 | |
39 | my ($xrot, $yrot, $xspeed, $yspeed); |
40 | my $z = -5.0; |
41 | |
42 | my $LightAmbient = [ 0.5, 0.5, 0.5, 1.0 ]; |
43 | my $LightDiffuse = [ 1.0, 1.0, 1.0, 1.0 ]; |
44 | my $LightPosition = [ 0.0, 0.0, 2.0, 1.0 ]; |
45 | |
46 | my $quadratic; |
47 | my $object = 5; |
48 | my $filter = 1; |
49 | |
50 | # this flag is used to limit key strokes event |
51 | my $pressed = 0; |
52 | |
53 | GetOptions |
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 | |
62 | main(); |
63 | exit; |
64 | |
65 | sub 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 | |
176 | sub 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 | |
213 | sub 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 | |
257 | sub 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 | |
316 | sub 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 | |
388 | sub 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 | |
437 | END |
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 | } |