orange has asked for the wisdom of the Perl Monks concerning the following question:

i have translated to the perl an opengl code written in thinbasic in the following link:
http://community.thinbasic.com/index.php?topic=2675.0
it is about a rotating Fan, the blades and the body of the fan are reflecting light well in the original code.
it is working well in perl opengl and rotating from left to right and vise versa with a one problem:
i can't make the blades of the fan to reflect the light as it should be, the mystery is that if i have deleted the body of the fan and just retain the rotating blades it well reflect the light, as in the picture:
http://sites.google.com/site/zak31415/Home/fan2.JPG
but with the presence of the fan body it will not as in this picture:
http://sites.google.com/site/zak31415/Home/fan1.JPG
you may download the file:
http://sites.google.com/site/zak31415/Home/Fan_For_Summer.pl
or the fan blades only:
http://sites.google.com/site/zak31415/Home/Fan_blades.pl
you can install opengl for window for active state perl 5.10 from here:
http://www.bribes.org/perl/ppmdir.html
and for installation:
ppm install http://www.bribes.org/perl/ppm/OpenGL.ppd
i wish there is a perl opengl forum, there is no such a forum, just the c/c++ forums.
References: OpenGL Programming Guide:http://glprogramming.com/red/index.html
the code is a collection from thinbasic site and the examples in POGL site: http://graphcomp.com/opengl/ , so forgive me for the may be a not necessary code
the code for the fan for summer is as the folowing:
#! /usr/bin/perl -w # Requires OpenGL module in addition to OpenGL use OpenGL qw(:all); # Use the OpenGL module use strict; # ASCII constant for the escape key use constant ESCAPE => 27; # Global variable for our window my $window; my $a;my $b; my $c; my $angle; my $speed; my $i; my $angle_horizontal=0; #rotation of the Fan body left and right my $angle_step = 0.3; my @position = (0.0, 0.0, 2.0, 1.0); my @light0_position = (5.0, 5.0, 5.0, 0.0); my @mat_specular = (1.0, 1.0, 1.0, 1.0); my @mat_shininess = (50.0); my @mat_amb_diff_color = (1.0, 0.5, 0.0, 0.5); my @light_diffuse = (1.0, 1.0, 1.0, 1.0); my @light_ambient = (0.15, 0.15, 0.15, 0.15); my @light_specular = (1.0, 1.0, 1.0, 1.0); # A general GL initialization function # Called right after our OpenGL window is created # Sets all of the initial parameters sub InitGL { # Shift the width and height off of @_, in that order my ($width, $height) = @_; glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel(GL_SMOOTH); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); # Reset the projection matrix glMatrixMode(GL_PROJECTION); glLoadIdentity; # Calculate the aspect ratio of the Window gluPerspective(45.0, $width/$height, 0.1, 100.0); # Reset the modelview matrix glMatrixMode(GL_MODELVIEW); } # The function called when our window is resized # This shouldn't happen, because we're fullscreen sub ReSizeGLScene { # Shift width and height off of @_, in that order my ($width, $height) = @_; # Prevent divide by zero error if window is too small if ($height == 0) { $height = 1; } # Reset the current viewport and perspective transformation glViewport(0, 0, $width, $height); # Re-initialize the window (same lines from InitGL) glMatrixMode(GL_PROJECTION); glLoadIdentity; gluPerspective(45.0, $width/$height, 0.1, 100.0); glMatrixMode(GL_MODELVIEW); } # The main drawing function. sub DrawGLScene { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLightfv_p(GL_LIGHT0, GL_POSITION, @light0_position); glLightfv_p(GL_LIGHT0, GL_DIFFUSE, @light_diffuse); glLightfv_p(GL_LIGHT0, GL_AMBIENT, @light_ambient); glLightfv_p(GL_LIGHT0, GL_SPECULAR, @light_specular); glMaterialfv_p(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,@mat_amb_diff_color); # Reset the screen glLoadIdentity; # Move to the into (inside) the screen 6.0 units glTranslatef(0.0, 0.0, -6.0); gluLookAt(5,5,5,0,1.5,0,0,1,0); &Fan_Physics(); &Fan_Render(); # Since this is double buffered, swap the buffers. # This will display what just got drawn. glutSwapBuffers; } # The function called whenever a key is pressed. sub keyPressed { # Shift the unsigned char key, and the x,y placement off @_, in # that order. my ($key, $x, $y) = @_; # Avoid thrashing this procedure # Note standard Perl does not support usleep # For finer resolution sleep than seconds, try: # 'select undef, undef, undef, 0.1;' # to sleep for (at least) 0.1 seconds sleep(1); # If f key pressed, undo fullscreen and resize to 640x480 if ($key == ord('f')) { # Use reshape window, which undoes fullscreen glutReshapeWindow(640, 480); } # If escape is pressed, kill everything. if ($key == ESCAPE) { # Shut down our window glutDestroyWindow($window); # Exit the program...normal termination. exit(0); } } sub Fan_Physics() { $angle_horizontal = $angle_horizontal + $angle_step; if ($angle_horizontal > 110) {$angle_step = -0.3;} else{if ($angle_horizontal < 0) { $angle_step = 0.3; } } $speed += 90/100; if ($speed > 600){ $speed = 600}; $angle += $speed/100; } sub Fan_Render{ glPushMatrix; #-- Base glPushMatrix; my $quad = OpenGL::gluNewQuadric(); gluQuadricDrawStyle($quad, GLU_FILL); glScalef( 4 , 0.5 , 4 ); #Sphere with radius 0.25 then scaled gluSphere( $quad , 0.25 , 20 , 20 ); glPopMatrix; glPushMatrix; glRotatef(-90, 1.0, 0.0, 0.0); gluCylinder($quad, 0.125, 0.125, 3, 16, 10); glPopMatrix; glPushMatrix; glTranslatef(0.0, 3.0, 0.0); glRotatef($angle_horizontal, 0, 1, 0); glScalef( 0.5, 0.5, 1); gluSphere( $quad , 1 , 20 , 20 ); glPopMatrix; # Fan $quad = OpenGL::gluNewQuadric(); gluQuadricDrawStyle($quad, GLU_FILL); glRotatef($angle_horizontal, 0, 1, 0); glPushMatrix; glTranslatef(0.0, 3.0, 0.5); glRotatef( $angle, 0.0, 0.0, 1.0 ); for ($i = 1; $i<=360; $i=$i+60) { glPushMatrix; glRotatef( $i, 0.0, 0.0, 1.0 ); glTranslatef(1.5, 0.0, 0.0); glRotatef( -45, 1.0, 0.0, 0.0 ); my @mat_amb_diff_color = (0.5, 1, 0.5, 0.5); glShadeModel(GL_FLAT); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glMaterialfv_p(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,@mat_amb_diff_color); glPushMatrix; #calling Box ie: drawing the Blade of the fan &Box(1, 0.3, 0.01); glEnable(GL_LIGHTING); glPopMatrix; glPopMatrix; } glPopMatrix; glPopMatrix; glPopMatrix; } sub Box { $a = $_[0]; $b = $_[1]; $c = $_[2]; glBegin(GL_QUADS); # Top face of box glVertex3f($a, $b, -$c); # Top right vertex (Top of cube) glVertex3f(-$a, $b, -$c); # Top left vertex (Top of cube) glVertex3f(-$a, $b, $c); # Bottom left vertex (Top of cube) glVertex3f($a, $b, $c); # Bottom right vertex (Top of cube) # Bottom face of box glVertex3f($a, -$b, -$c); # Top right vertex (Bottom of cube) glVertex3f(-$a, -$b, -$c); # Top left vertex (Bottom of cube) glVertex3f(-$a, -$b, $c); # Bottom left vertex (Bottom of cube) glVertex3f( $a, -$b, $c); # Bottom right vertex (Bottom of cube) # Front of box glVertex3f($a, $b, $c); # Top right vertex (Front) glVertex3f(-$a, $b, $c); # Top left vertex (Front) glVertex3f(-$a, -$b, $c); # Bottom left vertex (Front) glVertex3f($a, -$b, $c); # Bottom right vertex (Front) # Back of box glVertex3f($a, -$b, -$c); # Bottom right vertex (Back) glVertex3f(-$a, -$b, -$c); # Bottom left vertex (Back) glVertex3f(-$a, $b, -$c); # top left vertex (Back) glVertex3f($a, $b, -$c); # Top right vertex (Back) # Left of box glVertex3f(-$a, $b, $c); # Top right vertex (Left) glVertex3f(-$a, $b, -$c); # Top left vertex (Left) glVertex3f(-$a, -$b, -$c); # Bottom left vertex (Left) glVertex3f(-$a, -$b, $c); # Bottom vertex (Left) # Right of box glVertex3f($a, $b, -$c); # Top right vertex (Right) glVertex3f($a, $b, $c); # Top left vertex (Right) glVertex3f($a, -$b, $c); # Bottom left vertex (Right) glVertex3f($a, -$b, -$c); # Bottom right vertex (Right) # End drawing the box glEnd; } # --- Main program --- # Initialize GLUT state glutInit; # Select type of Display mode: # Double buffer # RGB color (Also try GLUT_RGBA) # Alpha components removed (try GLUT_ALPHA) # Depth buffer */ glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); # Get a 640 x 480 window glutInitWindowSize(640, 480); # The window starts at the upper left corner of the screen glutInitWindowPosition(0, 0); # Open the window $window = glutCreateWindow("Fan for Hot Summer -perl opengl example"); # Register the function to do all our OpenGL drawing. glutDisplayFunc(\&DrawGLScene); # Go fullscreen. This is as soon as possible. #glutFullScreen; glutReshapeWindow(640,480); # Even if there are no events, redraw our gl scene. glutIdleFunc(\&DrawGLScene); # Register the function called when our window is resized. glutReshapeFunc(\&ReSizeGLScene); # Register the function called when the keyboard is pressed. glutKeyboardFunc(\&keyPressed); # Initialize our window. InitGL(640, 480); # Start Event Processing Engine glutMainLoop; return 1;

Replies are listed 'Best First'.
Re: Fan For Summer, perl opengl example
by grizzley (Chaplain) on Jul 03, 2009 at 13:31 UTC
    I don't know OpenGL well, but I can notice at least one mistake in translation: in function Fan_Render you call glPopMatrix three times at the end. In original there are two. Please check the code carefully, for sure the reason of lack of light is easy to find.
      thank you, i have depended on the last updated code in the thinbasic page near the end of that page which makes the fan rotate from left to right and vice versa, it contains 3 PopMatrix ,
      it appears to me that the light is shining from behind the Fan, since if we change the perl line
      if ($angle_horizontal > 110)...
      to
      if ($angle_horizontal > 200)
      the fan will show us that it is lighted from behind.
      this is strange, since if we omit the body of the fan as in the file:
      http://sites.google.com/site/zak31415/Home/Fan_blades.pl
      it will be lighted from front