PageRenderTime 65ms CodeModel.GetById 25ms app.highlight 36ms RepoModel.GetById 1ms app.codeStats 0ms

/t_backcompat/OpenGL/tutorial/lesson07.pl

http://github.com/PerlGameDev/SDL
Perl | 352 lines | 239 code | 79 blank | 34 comment | 28 complexity | 8aafb3097db8d6abd365436f8638a891 MD5 | raw file
  1#!/usr/bin/perl
  2# This code is based on the code by Jeff Molofee '99
  3# and ported to SDL by Sam Lantinga '2000
  4# Original ported to Perl/SDL by Wayne Keenan '2000
  5# And updated by David Goehrig '02
  6#
  7#
  8# Jeff's tutorials can be found at www.demonews.com/hosted/nehe
  9
 10use strict;
 11use Getopt::Long;
 12use Data::Dumper;
 13use Benchmark;
 14
 15use SDL;
 16use SDLx::App;
 17use SDL::OpenGL;
 18use SDL::Event;
 19use SDL::Surface;
 20use SDL::OpenGL;
 21
 22my $arg_screen_width  = 640;
 23my $arg_screen_height = 512;
 24my $arg_fullscreen    = 0;
 25
 26GetOptions(
 27	"width:i"     => \$arg_screen_width,
 28	"height:i"    => \$arg_screen_height,
 29	"fullscreen!" => \$arg_fullscreen,
 30) or die $!;
 31
 32############################################################
 33
 34my $light = 0;
 35
 36my $xrot   = 0; # x rotation
 37my $yrot   = 0; # y rotation
 38my $xspeed = 0; # x rotation speed
 39my $yspeed = 0; # y rotation speed
 40
 41my $z = -5.0;   # depth into the screen.
 42
 43my $filter = 1; # Which Filter To Use (nearest/linear/mipmapped) */
 44
 45main();
 46exit;
 47
 48sub main {
 49	my $done          = 0;
 50	my $vidmode_flags = SDL_OPENGL;
 51
 52	$vidmode_flags |= SDL_FULLSCREEN if $arg_fullscreen;
 53
 54	my $app = SDLx::App->new(
 55		-title  => "Jeff Molofee's GL Code Tutorial ... NeHe '99",
 56		-icon   => "icon.png",
 57		-flags  => $vidmode_flags,
 58		-width  => $arg_screen_width,
 59		-height => $arg_screen_height,
 60		-opengl => 1,
 61	);
 62
 63	SDL::ShowCursor(0);
 64
 65	my $event = SDL::Event->new;
 66	$event->set( SDL_SYSWMEVENT, SDL_IGNORE );
 67
 68	InitGL( $arg_screen_width, $arg_screen_height );
 69
 70	while ( not $done ) {
 71
 72		DrawGLScene();
 73
 74		$app->sync();
 75
 76		$event->pump;
 77		$event->poll;
 78
 79		$done = 1 if ( $event->type == SDL_QUIT );
 80
 81		if ( $event->type == SDL_KEYDOWN ) {
 82			my $key = $event->key_sym;
 83
 84			$done = 1 if ( $key == SDLK_ESCAPE );
 85
 86			if ( $key == SDLK_l ) {
 87				printf( "Light was: %d\n", $light );
 88				$light =
 89					$light
 90					? 0
 91					: 1; # switch the current value of light, between 0 and 1.
 92				printf( "Light is now: %d\n", $light );
 93				if ( !$light ) {
 94					glDisable(GL_LIGHTING);
 95				} else {
 96					glEnable(GL_LIGHTING);
 97				}
 98
 99			}
100			if ( $key == SDLK_f ) {
101				printf( "Filter was: %d\n", $filter );
102				$filter = 1 + ( ($filter) % 3 );
103				printf( "Filter is now: %d\n", $filter );
104			}
105
106			#bit lax:
107			$z -= 0.02 if ( $key == SDLK_PAGEUP );
108			$z      += 0.02 if ( $key == SDLK_PAGEDOWN );
109			$xspeed += 0.02 if ( $key == SDLK_UP );
110			$xspeed -= 0.02 if ( $key == SDLK_DOWN );
111			$yspeed -= 0.01 if ( $key == SDLK_LEFT );
112			$yspeed += 0.01 if ( $key == SDLK_RIGHT );
113
114		}
115	}
116}
117
118#########################################################################
119#Pretty much in original form, but 'Perlised'
120
121sub InitGL {
122	my ( $Width, $Height ) = @_;
123
124	glViewport( 0, 0, $Width, $Height );
125
126	LoadGLTextures(); # Load The Texture(s)
127
128	glEnable(GL_TEXTURE_2D); # Enable Texture Mapping
129
130	glClearColor( 0.0, 0.0, 0.0, 0.0 ); # This Will Clear The Background Color To Black
131	glClearDepth(1.0);                  # Enables Clearing Of The Depth Buffer
132	glDepthFunc(GL_LESS);               # The Type Of Depth Test To Do
133	glEnable(GL_DEPTH_TEST);            # Enables Depth Testing
134	glShadeModel(GL_SMOOTH);            # Enables Smooth Color Shading
135
136	glMatrixMode(GL_PROJECTION);
137	glLoadIdentity();                   # Reset The Projection Matrix
138
139	gluPerspective( 45.0, $Width / $Height, 0.1, 100.0 ); # Calculate The Aspect Ratio Of The Window
140
141	glMatrixMode(GL_MODELVIEW);
142
143	my $LightAmbient = [ 0.5, 0.5, 0.5, 1.0 ];            # white ambient light at half intensity (rgba) */
144
145	my $LightDiffuse = [ 1.0, 1.0, 1.0, 1.0 ];            # super bright, full intensity diffuse light. */
146
147	my $LightPosition = [ 0.0, 0.0, 2.0, 1.0 ];           # position of light (x, y, z, (position of light)) */
148
149	#hmm, undefine:
150	glLight( GL_LIGHT1, GL_AMBIENT,  @$LightAmbient );    # add lighting. (ambient)
151	glLight( GL_LIGHT1, GL_DIFFUSE,  @$LightDiffuse );    # add lighting. (diffuse).
152	glLight( GL_LIGHT1, GL_POSITION, @$LightPosition );   # set light position.
153	glEnable(GL_LIGHT1);                                  # turn light 1 on.
154}
155
156# The main drawing function.
157sub DrawGLScene {
158	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); # Clear The Screen And The Depth Buffer
159	glLoadIdentity();                                     # Reset The View
160
161	glTranslate( 0.0, 0.0, $z );                          # move z units out from the screen.
162
163	glRotate( $xrot, 1.0, 0.0, 0.0 );                     # Rotate On The X Axis
164	glRotate( $yrot, 0.0, 1.0, 0.0 );                     # Rotate On The Y Axis
165
166	glBindTexture( GL_TEXTURE_2D, $filter );              # choose the texture to use.
167
168	glBegin(GL_QUADS);                                    # begin drawing a cube
169
170	# Front Face (note that the texture's corners have to match the quad's corners)
171	glNormal( 0.0, 0.0, 1.0 );                            # front face points out of the screen on z.
172	glTexCoord( 0.0, 0.0 );
173	glVertex( -1.0, -1.0, 1.0 );                          # Bottom Left Of The Texture and Quad
174	glTexCoord( 1.0, 0.0 );
175	glVertex( 1.0, -1.0, 1.0 );                           # Bottom Right Of The Texture and Quad
176	glTexCoord( 1.0, 1.0 );
177	glVertex( 1.0, 1.0, 1.0 );                            # Top Right Of The Texture and Quad
178	glTexCoord( 0.0, 1.0 );
179	glVertex( -1.0, 1.0, 1.0 );                           # Top Left Of The Texture and Quad
180
181	# Back Face
182	glNormal( 0.0, 0.0, -1.0 );                           # back face points into the screen on z.
183	glTexCoord( 1.0, 0.0 );
184	glVertex( -1.0, -1.0, -1.0 );                         # Bottom Right Of The Texture and Quad
185	glTexCoord( 1.0, 1.0 );
186	glVertex( -1.0, 1.0, -1.0 );                          # Top Right Of The Texture and Quad
187	glTexCoord( 0.0, 1.0 );
188	glVertex( 1.0, 1.0, -1.0 );                           # Top Left Of The Texture and Quad
189	glTexCoord( 0.0, 0.0 );
190	glVertex( 1.0, -1.0, -1.0 );                          # Bottom Left Of The Texture and Quad
191
192	# Top Face
193	glNormal( 0.0, 1.0, 0.0 );                            # top face points up on y.
194	glTexCoord( 0.0, 1.0 );
195	glVertex( -1.0, 1.0, -1.0 );                          # Top Left Of The Texture and Quad
196	glTexCoord( 0.0, 0.0 );
197	glVertex( -1.0, 1.0, 1.0 );                           # Bottom Left Of The Texture and Quad
198	glTexCoord( 1.0, 0.0 );
199	glVertex( 1.0, 1.0, 1.0 );                            # Bottom Right Of The Texture and Quad
200	glTexCoord( 1.0, 1.0 );
201	glVertex( 1.0, 1.0, -1.0 );                           # Top Right Of The Texture and Quad
202
203	# Bottom Face
204	glNormal( 0.0, -1.0, 0.0 );                           # bottom face points down on y.
205	glTexCoord( 1.0, 1.0 );
206	glVertex( -1.0, -1.0, -1.0 );                         # Top Right Of The Texture and Quad
207	glTexCoord( 0.0, 1.0 );
208	glVertex( 1.0, -1.0, -1.0 );                          # Top Left Of The Texture and Quad
209	glTexCoord( 0.0, 0.0 );
210	glVertex( 1.0, -1.0, 1.0 );                           # Bottom Left Of The Texture and Quad
211	glTexCoord( 1.0, 0.0 );
212	glVertex( -1.0, -1.0, 1.0 );                          # Bottom Right Of The Texture and Quad
213
214	# Right face
215	glNormal( 1.0, 0.0, 0.0 );                            # right face points right on x.
216	glTexCoord( 1.0, 0.0 );
217	glVertex( 1.0, -1.0, -1.0 );                          # Bottom Right Of The Texture and Quad
218	glTexCoord( 1.0, 1.0 );
219	glVertex( 1.0, 1.0, -1.0 );                           # Top Right Of The Texture and Quad
220	glTexCoord( 0.0, 1.0 );
221	glVertex( 1.0, 1.0, 1.0 );                            # Top Left Of The Texture and Quad
222	glTexCoord( 0.0, 0.0 );
223	glVertex( 1.0, -1.0, 1.0 );                           # Bottom Left Of The Texture and Quad
224
225	# Left Face
226	glNormal( -1.0, 0.0, 0.0 );                           # left face points left on x.
227	glTexCoord( 0.0, 0.0 );
228	glVertex( -1.0, -1.0, -1.0 );                         # Bottom Left Of The Texture and Quad
229	glTexCoord( 1.0, 0.0 );
230	glVertex( -1.0, -1.0, 1.0 );                          # Bottom Right Of The Texture and Quad
231	glTexCoord( 1.0, 1.0 );
232	glVertex( -1.0, 1.0, 1.0 );                           # Top Right Of The Texture and Quad
233	glTexCoord( 0.0, 1.0 );
234	glVertex( -1.0, 1.0, -1.0 );                          # Top Left Of The Texture and Quad
235
236	glEnd();                                              # done with the polygon.
237
238	$xrot += $xspeed;                                     # X Axis Rotation
239	$yrot += $yspeed;                                     # Y Axis Rotation
240
241}
242
243sub LoadGLTextures {
244
245	# Load Texture
246
247	my ( $pixels, $width, $height, $size ) = ImageLoad("Data/crate.png");
248
249	# Create Texture
250
251	glGenTextures(3);
252
253	# texture 1 (poor quality scaling)
254	glBindTexture( GL_TEXTURE_2D, 1 ); # 2d texture (x and y size)
255
256	glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); # cheap scaling when image bigger than texture
257	glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); # cheap scaling when image smalled than texture
258
259	# 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image,
260	# border 0 (normal), rgb color data, unsigned byte data, and finally the data itself.
261	#glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->w, image1->h, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->pixels);
262
263	glTexImage2D( GL_TEXTURE_2D,
264		0,                                                              #level (0 normal, heighr is form mip-mapping)
265		3,                                                              #internal format (3=GL_RGB)
266		$width, $height,
267		0,                                                              # border
268		GL_RGB,                                                         #format RGB color data
269		GL_UNSIGNED_BYTE,                                               #unsigned bye data
270		$pixels
271	);                                                                  #ptr to texture data
272
273	# texture 2 (linear scaling)
274	glBindTexture( GL_TEXTURE_2D, 2 );                                  # 2d texture (x and y size)
275	glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );  # scale linearly when image bigger than texture
276	glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );  # scale linearly when image smalled than texture
277	   #glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->w, image1->h, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->pixels);
278
279	glTexImage2D( GL_TEXTURE_2D,
280		0, #level (0 normal, heighr is form mip-mapping)
281		3, #internal format (3=GL_RGB)
282		$width, $height,
283		0,                # border
284		GL_RGB,           #format RGB color data
285		GL_UNSIGNED_BYTE, #unsigned bye data
286		$pixels
287	);                    #ptr to texture data
288
289	# texture 3 (mipmapped scaling)
290	glBindTexture( GL_TEXTURE_2D, 3 ); # 2d texture (x and y size)
291	glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); # scale linearly when image bigger than texture
292	glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
293		GL_LINEAR_MIPMAP_NEAREST
294	); # scale linearly + mipmap when image smalled than texture
295	   #glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->w, image1->h, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->pixels);
296
297	glTexImage2D( GL_TEXTURE_2D,
298		0, #level (0 normal, heighr is form mip-mapping)
299		3, #internal format (3=GL_RGB)
300		$width, $height,
301		0,                # border
302		GL_RGB,           #format RGB color data
303		GL_UNSIGNED_BYTE, #unsigned bye data
304		$pixels
305	);                    #ptr to texture data
306
307	# 2d texture, 3 colors, width, height, RGB in that order, byte data, and the data.
308	gluBuild2DMipmaps( GL_TEXTURE_2D, 3, $width, $height, GL_RGB,
309		GL_UNSIGNED_BYTE, $pixels
310	);
311
312	my $glerr = glGetError();
313	die "Problem setting up 2d Texture (dimensions not a power of 2?)):" . gluErrorString($glerr) . "\n"
314		if $glerr;
315
316}
317
318#somthing needs to keep the ref count alive for objects which represents data in C space (they have no ref count):
319my @ref = ();
320
321sub ImageLoad {
322	my $filename = shift;
323
324	my $surface = SDL::Surface->new( -name => $filename ); #makes use of SDL: BMP loader.
325
326	my $width   = $surface->width();
327	my $height  = $surface->height();
328	my $bytespp = $surface->bytes_per_pixel();
329	my $size    = $width * $height * $bytespp;
330
331	my $surface_pixels = $surface->pixels();
332	my $surface_size   = $width * $height * $surface->bytes_per_pixel();
333	my $raw_pixels     = $surface_pixels;
334
335	#do a conversion (the pixel data is accessable as a simple string)
336
337	my $pixels     = $raw_pixels;
338	my $pre_conv   = $pixels;    #rotate image 180 degrees!
339	my $new_pixels = "";
340	for ( my $y = 0; $y < $height; $y++ ) {
341		my $y_pos = $y * $width * $bytespp;                       #calculate offset into the image (a string)
342		my $row = substr( $pre_conv, $y_pos, $width * $bytespp ); #extract 1 pixel row
343		$row =~ s/\G(.)(.)(.)/$3$2$1/gms;                         #turn the BMP BGR order into OpenGL RGB order;
344		$new_pixels .= reverse $row;
345	}
346
347	$raw_pixels = $new_pixels;                                    #put transformed data into C array.
348	push @ref, $raw_pixels, $surface;
349
350	#we could have created another SDL surface frm the '$raw_pixel's... oh well.
351	return ( $raw_pixels, $width, $height, $size );
352}