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.
268 lines
6.9 KiB
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;
|