You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
libtqt-perl/PerlTQt/examples/opengl/gear/gear

268 lines
6.9 KiB

#!/usr/bin/perl -w
#
# Draws a gear.
#
# This code is originally from TQt-1.44, by Troll Tech
#
# Portions of this code have been borrowed from Brian Paul's Mesa
# distribution.
#
package GearWidget;
use OpenGL qw(:all);
use TQt;
use TQt::attributes qw(
gear1
gear2
gear3
view_rotx
view_roty
view_rotz
angle
);
use TQt::isa qw(TQt::GLWidget);
#
# Draw a gear wheel. You'll probably want to call this function when
# building a display list since we do a lot of trig here.
#
# Input: inner_radius - radius of hole at center
# outer_radius - radius at center of teeth
# width - width of gear
# teeth - number of teeth
# tooth_depth - depth of tooth
#
sub gear {
my($inner_radius, $outer_radius, $width, $teeth, $tooth_depth) = @_;
my $i;
my($r0, $r1, $r2);
my($angle, $da);
my($u, $v, $len);
$r0 = $inner_radius;
$r1 = $outer_radius - $tooth_depth/2.0;
$r2 = $outer_radius + $tooth_depth/2.0;
my $pi = 3.141592654;
$da = 2.0*$pi / $teeth / 4.0;
glShadeModel(GL_FLAT);
glNormal3f(0.0, 0.0, 1.0);
# draw front face
glBegin(GL_QUAD_STRIP);
for $i (0 .. $teeth) {
$angle = $i * 2.0*$pi / $teeth;
glVertex3f($r0*cos($angle), $r0*sin($angle), $width*0.5);
glVertex3f($r1*cos($angle), $r1*sin($angle), $width*0.5);
glVertex3f($r0*cos($angle), $r0*sin($angle), $width*0.5);
glVertex3f($r1*cos($angle+3*$da), $r1*sin($angle+3*$da), $width*0.5);
}
glEnd();
# draw front sides of teeth
glBegin(GL_QUADS);
$da = 2.0*$pi / $teeth / 4.0;
for $i (0 .. $teeth-1) {
$angle = $i * 2.0*$pi / $teeth;
glVertex3f($r1*cos($angle), $r1*sin($angle), $width*0.5);
glVertex3f($r2*cos($angle+$da), $r2*sin($angle+$da), $width*0.5);
glVertex3f($r2*cos($angle+2*$da), $r2*sin($angle+2*$da), $width*0.5);
glVertex3f($r1*cos($angle+3*$da), $r1*sin($angle+3*$da), $width*0.5);
}
glEnd();
glNormal3f(0.0, 0.0, -1.0);
# draw back face
glBegin(GL_QUAD_STRIP);
for $i (0 .. $teeth) {
$angle = $i * 2.0*$pi / $teeth;
glVertex3f($r1*cos($angle), $r1*sin($angle), -$width*0.5);
glVertex3f($r0*cos($angle), $r0*sin($angle), -$width*0.5);
glVertex3f($r1*cos($angle+3*$da), $r1*sin($angle+3*$da), -$width*0.5);
glVertex3f($r0*cos($angle), $r0*sin($angle), -$width*0.5);
}
glEnd();
# draw back sides of teeth
glBegin(GL_QUADS);
$da = 2.0*$pi / $teeth / 4.0;
for $i (0 .. $teeth-1) {
$angle = $i * 2.0*$pi / $teeth;
glVertex3f($r1*cos($angle+3*$da), $r1*sin($angle+3*$da), -$width*0.5);
glVertex3f($r2*cos($angle+2*$da), $r2*sin($angle+2*$da), -$width*0.5);
glVertex3f($r2*cos($angle+$da), $r2*sin($angle+$da), -$width*0.5);
glVertex3f($r1*cos($angle), $r1*sin($angle), -$width*0.5);
}
glEnd();
# draw outward faces of teeth
glBegin(GL_QUAD_STRIP);
for $i (0 .. $teeth-1) {
$angle = $i * 2.0*$pi / $teeth;
glVertex3f($r1*cos($angle), $r1*sin($angle), $width*0.5);
glVertex3f($r1*cos($angle), $r1*sin($angle), -$width*0.5);
$u = $r2*cos($angle+$da) - $r1*cos($angle);
$v = $r2*sin($angle+$da) - $r1*sin($angle);
$len = sqrt($u*$u + $v*$v);
$u /= $len;
$v /= $len;
glNormal3f($v, -$u, 0.0);
glVertex3f($r2*cos($angle+$da), $r2*sin($angle+$da), $width*0.5);
glVertex3f($r2*cos($angle+$da), $r2*sin($angle+$da), -$width*0.5);
glNormal3f(cos($angle), sin($angle), 0.0);
glVertex3f($r2*cos($angle+2*$da), $r2*sin($angle+2*$da), $width*0.5);
glVertex3f($r2*cos($angle+2*$da), $r2*sin($angle+2*$da), -$width*0.5);
$u = $r1*cos($angle+3*$da) - $r2*cos($angle+2*$da);
$v = $r1*sin($angle+3*$da) - $r2*sin($angle+2*$da);
glNormal3f($v, -$u, 0.0);
glVertex3f($r1*cos($angle+3*$da), $r1*sin($angle+3*$da), $width*0.5);
glVertex3f($r1*cos($angle+3*$da), $r1*sin($angle+3*$da), -$width*0.5);
glNormal3f(cos($angle), sin($angle), 0.0);
}
glVertex3f($r1*cos(0.0), $r1*sin(0.0), $width*0.5);
glVertex3f($r1*cos(0.0), $r1*sin(0.0), -$width*0.5);
glEnd();
glShadeModel(GL_SMOOTH);
# draw inside radius cylinder
glBegin(GL_QUAD_STRIP);
for $i (0 .. $teeth) {
$angle = $i * 2.0*$pi / $teeth;
glNormal3f(-cos($angle), -sin($angle), 0.0);
glVertex3f($r0*cos($angle), $r0*sin($angle), -$width*0.5);
glVertex3f($r0*cos($angle), $r0*sin($angle), $width*0.5);
}
glEnd();
}
sub draw {
angle += 2.0;
view_roty += 1.0;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glRotatef(view_rotx, 1.0, 0.0, 0.0);
glRotatef(view_roty, 0.0, 1.0, 0.0);
glRotatef(view_rotz, 0.0, 0.0, 1.0);
glPushMatrix();
glTranslatef(-3.0, -2.0, 0.0);
glRotatef(angle, 0.0, 0.0, 1.0);
glCallList(gear1);
glPopMatrix();
glPushMatrix();
glTranslatef(3.1, -2.0, 0.0);
glRotatef(-2.0*angle-9.0, 0.0, 0.0, 1.0);
glCallList(gear2);
glPopMatrix();
glPushMatrix();
glTranslatef(-3.1, 2.2, -1.8);
glRotatef(90.0, 1.0, 0.0, 0.0);
glRotatef(2.0*angle-2.0, 0.0, 0.0, 1.0);
glCallList(gear3);
glPopMatrix();
glPopMatrix();
}
sub NEW {
shift->SUPER::NEW(@_);
this->startTimer(10);
view_rotx = 20.0;
view_roty = 30.0;
view_rotz = 0.0;
angle = 0.0;
}
sub initializeGL {
my $pos = [ 5.0, 5.0, 10.0, 1.0 ];
my $red = [ 0.8, 0.1, 0.0, 1.0 ];
my $green = [ 0.0, 0.8, 0.2, 1.0 ];
my $blue = [ 0.2, 0.2, 1.0, 1.0 ];
glLightfv_p(GL_LIGHT0, GL_POSITION, @$pos);
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
# make the gears
gear1 = glGenLists(1);
glNewList(gear1, GL_COMPILE);
glMaterialfv_p(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, @$red);
gear(1.0, 4.0, 1.0, 20, 0.7);
glEndList();
gear2 = glGenLists(1);
glNewList(gear2, GL_COMPILE);
glMaterialfv_p(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, @$green);
gear(0.5, 2.0, 2.0, 10, 0.7);
glEndList();
gear3 = glGenLists(1);
glNewList(gear3, GL_COMPILE);
glMaterialfv_p(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, @$blue);
gear(1.3, 2.0, 0.5, 10, 0.7);
glEndList();
glEnable(GL_NORMALIZE);
}
sub resizeGL {
my($width, $height) = @_;
my $w = $width / $height;
my $h = 1.0;
glViewport(0, 0, $width, $height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-$w, $w, -$h, $h, 5.0, 60.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -40.0);
}
sub paintGL {
draw();
}
sub timerEvent {
updateGL();
}
package main;
use TQt;
use GearWidget;
$app = TQt::Application(\@ARGV);
if(!TQt::GLFormat::hasOpenGL()) {
warn("This system has no OpenGL support. Exiting.");
exit -1;
}
$w = GearWidget;
$app->setMainWidget($w);
$w->show;
exit $app->exec;