use OpenGL;
#3 Torus and Villarceau circles
This program shows the torus as the envelope its
Villarceau circles.
villarceau.pl
#!/usr/local/bin/perl
#
# villarceau.pl : generates a torus by its Villarceau circles
# (c) 2013 jl_morel@bribes.org - http://http://bribes.org/perl
use strict;
use warnings;
use OpenGL qw/ :all /;
my @light0_position = ( 2.0, 8.0, 2.0, 0.0 );
my @mat_amb_diff_color = ( 0.9, 0.7, 0.5, 1 );
my @light_diffuse = ( 1.0, 1.0, 1.0, 1 );
my @light_ambient = ( 0.15, 0.15, 0.15, 1 );
#------ Base vectors
my @i = ( 1, 0, 0 );
my @j = ( 0, 1, 0 );
my @k = ( 0, 0, 1 );
#------ Initialization routine
sub init {
glClearColor( 1, 1, 1, 1 ); # White background
glShadeModel(GL_SMOOTH); # Smooth shading
glEnable(GL_DEPTH_TEST); # Enable hidden surface removal
glEnable(GL_MULTISAMPLE); # Enable multisample antialiasing
glEnable(GL_LIGHTING); # Enable lighting
glEnable(GL_LIGHT0);
glLightfv_p( GL_LIGHT0, GL_POSITION, @light0_position );
glLightfv_p( GL_LIGHT0, GL_DIFFUSE, @light_diffuse );
glLightfv_p( GL_LIGHT0, GL_AMBIENT, @light_ambient );
glMaterialfv_p( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, @mat_amb_diff_color );
glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
glEnable(GL_COLOR_MATERIAL); # Material track the current color
}
#------ Draw a circle in space
# We draw a circle in space as a torus with a small inner radius
my $R = 3; # Outer radius of the torus
my $r = 0.08; # Inner radius of the torus.
my $beta = 20; # Inclination
my $spin = 0.0; # Rotation angle
sub Drawcircle {
my $alpha = shift;
glPushMatrix();
glRotatef( $alpha, @k ); # Movement of the torus
glTranslatef( @j ); # Translation and inclination
glRotatef( $beta, @j ); # of the plane of the circle
glutSolidTorus( $r, $R, 10, 100 ); # The circle!
glPopMatrix();
}
#------ Draw the torus
sub display {
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glLightfv_p( GL_LIGHT0, GL_POSITION, @light0_position );
glLoadIdentity();
gluLookAt( 2.0, 4.0, 10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 );
glPushMatrix();
glRotatef( $spin, @j );
for ( my $a = 0 ; $a < 360 ; $a += 10 ) { # 36 circles
glColor3f( Rainbow( $a / 360 ) ); # of 36 different colors
Drawcircle($a);
}
glPopMatrix();
glutSwapBuffers();
# debug code
# if ( ( my $e = glGetError() ) != GL_NO_ERROR ) {
# print "error : ", gluErrorString($e), "\n";
# }
}
#------ GLUT Callback called when the window is resized
sub reshape {
my ( $w, $h ) = @_;
glViewport( 0, 0, $w, $h );
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); # define the projection
gluPerspective( 45.0, $h ? $w / $h : 0, 1.0, 20.0 );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
#------ Routine for rotating the torus
my $WaitUntil = 0;
sub spinDisplay {
my $TimeNow = glutGet(GLUT_ELAPSED_TIME);
if ( $TimeNow >= $WaitUntil ) {
$spin += 1.0;
$spin = $spin - 360.0 if ( $spin > 360.0 );
glutPostRedisplay();
$WaitUntil = $TimeNow + 1000 / 25; # 25 frames/s
}
}
#------ Main
glutInit();
glutInitDisplayMode(
GLUT_DOUBLE # Double buffering
| GLUT_RGB # RGB mode
| GLUT_DEPTH # Hidden surface removal
| GLUT_MULTISAMPLE # Multisample antialiasing
);
glutInitWindowPosition( 0, 0 );
glutInitWindowSize( 300, 300 );
glutCreateWindow("Torus");
init();
glutDisplayFunc( \&display );
glutReshapeFunc( \&reshape );
glutIdleFunc( \&spinDisplay );
glutMainLoop();
#------ Rainbow color map function
# Usage: ($red, $green, $blue) = Rainbow( $x );
# $x must be between 0 and 1.
# Returns the color of the rainbow (RGB list) associated with $x
# from blue for $x = 0 to red for $x = 1.
sub max { $_[0] < $_[1] ? $_[1] : $_[0] } # max auxiliary function
sub Rainbow {
my $dx = 0.8;
my $s = ( 6 - 2 * $dx ) * $_[0] + $dx;
return max( 0, ( 3 - abs( $s - 4 ) - abs( $s - 5 ) ) / 2 ), # Red
max( 0, ( 4 - abs( $s - 2 ) - abs( $s - 4 ) ) / 2 ), # Green
max( 0, ( 3 - abs( $s - 1 ) - abs( $s - 2 ) ) / 2 ); # Blue
}
Color palette for this Rainbow color map function:
The script as .txt for download:
villarceau.pl.txt
Back to Top
BðP © 2013 J-L Morel - Contact : jl_morel@bribes.org