#!/usr/bin/perl # # Name: GLgraph # # Version: 0.1.3 # # License: GPL # # 2002/04/12 Jonas Jermann # # pfy rulez! (He told me to write it down... ;-) # ################################################################################ # # Modules use OpenGL ":old",":glutfunctions",":gluconstants",":functions"; use Time::HiRes qw (gettimeofday tv_interval usleep); use strict; no strict "subs"; use Math::Trig; ################################################################################ # # Variables our ($PI,$tsize,$zsize,$time,$n,$z,$t,@tri2d,@tri3d, @yreal,@options,$cfact,$fps,$xmin,$xmax,$ymin,$ymax,$zmin,$zmax,$tmin,$tmax,$xres,$zres,$tres, $width,$height); @options = (2,0,0,1); # 0(0): 2d # 0(1): 3d wire # 0(2): 3d solid # 1(0): stable # 1(1): time-function forward # 1(2): time-function backward # 2(0): orthographic viewing # 2(1): perspective viewing # 2(2): stereo viewing # 2(3): 2nd way of stereo viewing # 3(0): no colours # 3(1): color-mode 1 # 3(2): color-mode 2 (pfy) # Window $xmin = -5; $xmax = 5; $ymin = -5; $ymax = 4; $zmin = -5; $zmax = 5; $tmin = -4; $tmax = 4; # Axis and misc $xres = 40; $zres = 50; $tres = 50; $fps = 30; $cfact = 1.5; # Init $z = $zmin; $t = $tmin; $n = 0; $time = [gettimeofday]; $zsize = 0; $tsize = 0; $PI = 3.415926535898; ################################################################################ # # Main init(); glutMainLoop; ################################################################################ # # Sub # INIT sub init{ # glut init glutInit(@ARGV); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(1024, 768); glutInitWindowPosition(0, 0); glutCreateWindow("graph window"); glutFullScreen(); # functions glutKeyboardFunc(\&keyboard); glutDisplayFunc(\&display); glutReshapeFunc(\&resize); glutIdleFunc(\&idle); glClearColor(0,0,0,0); glMatrixMode(GL_PROJECTION); glOrtho($xmin,$xmax,$ymin,$ymax,$zmin,$zmax); glRotatef(-50, 5, -0.5, 0.0); glScalef(0.8,0.8,0.8); reset(); } # COLOR sub scolor { if ($options[3] == 1) { glColor3f(0.8*sin($_[0]*$cfact),0.8*sin($_[0]*$cfact+2*$PI/3),0.8*sin($_[0]*$cfact+4*$PI/3)); } elsif ($options[3] == 2) { my ($r,$b,$g,$a); $r=$b=$g=0; $a=(($_[0]-$ymin)/($ymax-$ymin)*$cfact); $r=$a*3; $r=1 if ($r > 1); $g=($a*3-1) if ((($a*3-1) > 0)); $g=1 if ($g > 1); $b=($a*3-2) if ((($a*3-2) > 0)); $b=1 if ($b > 1); glColor3f($r,$g,$b); } } sub resize{ ($width,$height)=@_; } sub reset { # gl init glLoadIdentity(); # window properties glFlush(); # calculation idle(); } # IDLE sub idle { $yreal[0] = '2*cos(t*sqrt(z*z+x*x)-2*atan(x/z))'; $yreal[1] = '(cos(t*sqrt(z*z+x*x))-sin(t*sqrt(z*z+x*x)))*exp(-sqrt(z*z+x*x))*5'; $yreal[2] = '0.1*z*sin(t*(z-x))-x*cos(z*x-t)'; $yreal[3] = 'sqrt(t*(1-z*z-x*x))'; $yreal[4] = 'sin(x*x+z*z+t*t)'; $yreal[$n] =~ s/(? 0)) { $zsize=0; $z=$zmin; $t -= ($tmax-$tmin)/($tres-1); $tsize--; } elsif ($options[1] == 1) { $options[1]=2; } elsif ($options[1] == 2) { $options[1]=1; } } # MAIN DISPLAY sub display { if (tv_interval($time)<(1/$fps)) { usleep (1/120); return; } $time = [gettimeofday]; glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f(0.8,0.8,0.8); if ($options[0] == 0) { display_2d(); } elsif ($options[0] == 1) { display_3dwire(); } elsif ($options[0] == 2) { display_3d(); } glFlush(); glutSwapBuffers(); } # KEYBOARD sub keyboard { my ($key) = @_; $key = chr($key); # misc if ($key=~/q/i){ exit(); } elsif($key=~/m/i){ screenshot(); } elsif($key=~/3/i){ $cfact=$cfact*0.98; } elsif($key=~/4/i){ $cfact=$cfact*1.02; } # function change elsif($key=~/n/i){ $n++; $zsize=0; $z=$zmin; } elsif(($key=~/b/i) and ($n > 0)){ $n--; $zsize=0; $z=$zmin; } # mode change elsif(($key=~/1/i) and ($options[0]>0)){ $options[0]--; $zsize=0; $z=$zmin; } elsif(($key=~/2/i) and ($options[0]<2)){ $options[0]++; $zsize=0; $z=$zmin; } elsif($key=~/c/i) { if ($options[3] < 3) { $options[3]++; } if ($options[3] >=3) { $options[3]=0; } } elsif($key=~/t/i) { if ($options[1] == 0) { $options[1]=1; } else { $options[1]=0; } } # Seeking elsif($key=~/x/i) { $zsize=0; $z=$zmin; if (($options[1] > 0) and ($tsize <= ($tres-5))) { $t += 5*($tmax-$tmin)/($tres-1); $tsize=$tsize+5; } elsif ($tsize < $tres) { $t += ($tmax-$tmin)/($tres-1); $tsize++; } } elsif($key=~/y/i) { $zsize=0; $z=$zmin; if (($options[1] > 0) and ($tsize >= 5)) { $t -= 5*($tmax-$tmin)/($tres-1); $tsize=$tsize-5; } elsif ($tsize > 0) { $t -= ($tmax-$tmin)/($tres-1); $tsize--; } } # resolution (! BUGGY !) elsif($key=~/u/i){ $t=$tmin; $z=$zmin; $xres=int($xres*1.1+0.9); $zres=int($zres*1.1+0.9); } elsif($key=~/z/i){ $t=$tmin; $z=$zmin; $xres=int($xres*0.91+0.2); $zres=int($zres*0.91+0.2); } elsif($key=~/j/i){ $t=$tmin; $z=$zmin; $tsize=0; $zsize=0; $tres=int($tres*1.1+0.9); } elsif($key=~/h/i){ $t=$tmin; $z=$zmin; $tsize=0; $zsize=0; $tres=int($tres*0.91+0.2); } # rotation elsif($key=~/w/i){ glRotatef(3, 1, 0, 0); } elsif($key=~/s/i){ glRotatef(-3, 1, 0, 0); } elsif($key=~/a/i){ glRotatef(3, 0, 1, 0); } elsif($key=~/d/i){ glRotatef(-3, 0, 1, 0); } # translation elsif($key=~/\ü/i){ glTranslatef(0, 0.5, 0); } elsif($key=~/\ä/i){ glTranslatef(0, -0.5, 0); } elsif($key=~/\ö/i){ glTranslatef(-0.5, 0, 0); } elsif($key=~/\$/i){ glTranslatef(0.5, 0, 0); } # Scaling elsif($key=~/r/i){ glScalef(1.1,1.1,1.1); } elsif($key=~/e/i){ glScalef(0.91,0.91,0.91); } # repaint the window display(); } # SCREENSHOT HEADER sub getheader{ my $header; my ($width,$height) = @_; $header = pack("s",hex("4d42")); #signature $header .= pack("i",$width*$height*3+hex(36));#size (inc header) $header .= pack("s",0); #reserved $header .= pack("s",0); #reserved $header .= pack("i",hex(36)); #offset $header .= pack("i",40); #size of BITMAPINFOHEADER structure, must be 40 $header .= pack("i",$width); #width $header .= pack("i",$height); #hight $header .= pack("s",1); #number of planes in the image, must be 1 $header .= pack("s",24); #bites per pixel $header .= pack("i",0); #compression type (0=none, 1=RLE-8, 2=RLE-4) $header .= pack("i",$width*$height*3); #size of image data $header .= pack("i",0); #horizontal resolution in pixels per meter (unreliable) $header .= pack("i",0); #vertical resolution in pixels per meter (unreliable) $header .= pack("i",0); #number of colors in image, or zero $header .= pack("i",0); #number of important colors, or zero return $header; } # SCREENSHOT sub screenshot { my $num = 1; my $i; $num++ while(-f "image$num.bmp"); if(open(IMAGE,">image$num.bmp")){ print IMAGE getheader($width,$height); my @pixels=glReadPixels_p(0, 0,$width,$height, GL_RGB,GL_UNSIGNED_INT); #{print (IMAGE pack("B*", $i )); }for $i (@pixels); for $i (0..(($#pixels-1)/3)){ my ($red, $green, $blue) = ($pixels[$i*3],$pixels[$i*3+1],$pixels[$i*3+2]); print IMAGE pack("B B B",$blue,$green,$red); } #for $pixel (@pixels){ print IMAGE pack ("B*",$pixel);} close(IMAGE); } } # SUB IDLE (2D) sub idle_2d { my (@tripar,$x,$y,$j); $x=$xmin; $j=0; while ($j<=(2*$xres-2)) { $y = eval($yreal[$n]); $tripar[$j]=$x; $tripar[$j+1]=$y; $x += ($xmax-$xmin)/($xres-1); $j=$j+2; } $j = 0; $zsize = $zres + 1; unshift(@tri2d,@tripar); splice(@tri2d,(2*$xres)); } # SUB IDLE (3D) sub idle_3d { my (@tripar,$x,$y,$j); $x=$xmin; $j=0; while ($j<=(3*$xres-3)) { $y = eval($yreal[$n]); $tripar[$j]=$x; $tripar[$j+1]=$y; $tripar[$j+2]=$z; $x += ($xmax-$xmin)/($xres-1); $j=$j+3; } $j = 0; $z += ($zmax-$zmin)/($zres-1); $zsize++; unshift(@tri3d,@tripar); splice(@tri3d,(9*$xres*$zres)); } # SUB DISPLAY (2D) sub display_2d { my $i; glBegin(GL_LINE_STRIP); { if ($options[3] > 0) {scolor($tri2d[1]);} glVertex2f($tri2d[0],$tri2d[1]); for ($i=2; $i<=(2*$xres-2); $i=$i+2) { if ($options[3] > 0) {scolor($tri2d[$i+1]); } glVertex2f($tri2d[$i],$tri2d[$i+1]);} } glEnd(); } # SUB DISPLAY (3D WIRE) sub display_3dwire { my ($h,$i); for $h (0..($zsize-2)) { glBegin(GL_LINE_STRIP); { # jeweils um einen Punkt springen for ($i=0; $i<=(3*$xres-4); $i=$i+3) { my $basec = $i+1+3*$h*$xres; # left bottom if ($options[3] > 0) {scolor($tri3d[$basec]); } glVertex3f($tri3d[$basec-1],$tri3d[$basec],$tri3d[$basec+1]); # left top if ($options[3] > 0) {scolor($tri3d[$basec+3*$xres]); } glVertex3f($tri3d[$basec-1+3*$xres],$tri3d[$basec+3*$xres],$tri3d[$basec+1+3*$xres]); # rigth top if ($options[3] > 0) {scolor($tri3d[$basec+3+3*$xres]); } glVertex3f($tri3d[$basec+2+3*$xres],$tri3d[$basec+3+3*$xres],$tri3d[$basec+4+3*$xres]); # left bottom if ($options[3] > 0) {scolor($tri3d[$basec]); } glVertex3f($tri3d[$basec-1],$tri3d[$basec],$tri3d[$basec+1]); } if ($options[3] > 0) {scolor($tri3d[3*$xres-2+3*$h*$xres]); } glVertex3f($tri3d[3*$xres-3+3*$h*$xres],$tri3d[3*$xres-2+3*$h*$xres],$tri3d[3*$xres-1+3*$h*$xres]); if ($options[3] > 0) {scolor($tri3d[3*$xres-2+3*$h*$xres+3*$xres]); } glVertex3f($tri3d[3*$xres-3+3*$h*$xres+3*$xres],$tri3d[3*$xres-2+3*$h*$xres+3*$xres],$tri3d[3*$xres-1+3*$h*$xres+3*$xres]); } glEnd(); } } # SUB DISPLAY (3D SOLID) sub display_3d { my ($h,$i); $time = [gettimeofday]; glBegin(GL_TRIANGLES); { for $h (0..($zsize-2)) { for ($i=0; $i<=(3*$xres-4); $i=$i+3) { my $basec = $i+1+3*$h*$xres; # left bottom if ($options[3] > 0) {scolor($tri3d[$basec]); } glVertex3f($tri3d[$basec-1],$tri3d[$basec],$tri3d[$basec+1]); # left top if ($options[3] > 0) {scolor($tri3d[$basec+3*$xres]); } glVertex3f($tri3d[$basec+3*$xres-1],$tri3d[$basec+3*$xres],$tri3d[$basec+3*$xres+1]); # right bottom if ($options[3] > 0) {scolor($tri3d[$basec+3]); } glVertex3f($tri3d[$basec+2],$tri3d[$basec+3],$tri3d[$basec+4]); # left top if ($options[3] > 0) {scolor($tri3d[$basec+3*$xres]); } glVertex3f($tri3d[$basec+3*$xres-1],$tri3d[$basec+3*$xres],$tri3d[$basec+3*$xres+1]); # right top if ($options[3] > 0) {scolor($tri3d[$basec+3*$xres+3]); } glVertex3f($tri3d[$basec+3*$xres+2],$tri3d[$basec+3*$xres+3],$tri3d[$basec+3*$xres+4]); # right bottom if ($options[3] > 0) {scolor($tri3d[$basec+3]); } glVertex3f($tri3d[$basec+2],$tri3d[$basec+3],$tri3d[$basec+4]); } } } glEnd(); }