BP

Previous

Next


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:

   palette

The script as .txt for download: villarceau.pl.txt

Back to Top


BP 2013 J-L Morel - Contact : jl_morel@bribes.org [Validation HTML 4.0!]