#!/usr/bin/perl # # Name: GLgraph # # Version: 0.2.2 # # License: GPL # # 2002/07/01 Jonas Jermann # David Gunzinger # # ################################################################################ # # M O D U L E S use OpenGL ":old",":glutfunctions",":gluconstants",":functions"; use strict; no strict "subs"; use Math::Trig; use Getopt::Long; #use Time::HiRes qw (gettimeofday tv_interval usleep); #TODO ################################################################################ # # M A I N # Variables our (%options,$xres_real,$zres_real,@geometry,@tri2d,@tri3d,@yreal,$PI,$n,$z,$t,$time,$zsize,$tsize); options(); commandline(); init(); if ($options{mode} <=1 ) { reset_all(2); } else { reset_all(3); } idle(); glutMainLoop; ################################################################################ # # S U B # VERSION sub version { my $version_string = "0.2.2"; print "GLgraph version $version_string\n"; exit; } # RESIZE : TODO sub resize { ($options{width},$options{height})=@_; # reset_all(3); } # RESET sub reset_all { # Variables (Space) $z = $options{zmin}; $zsize = 0; if ($_[0] >= 1) { # Variables (Time) $t = $options{tmin}; $tsize = 0; if ($_[0] >=2) { glLoadIdentity(); glFlush(); glOrtho($options{xmin},$options{xmax},$options{ymin},$options{ymax},$options{zmin},$options{zmax}); if ($_[0] >=3) { glRotatef(-50, 5, -0.5, 0.0); glScalef(0.8,0.8,0.8); } } } } # MAIN DISPLAY sub display { glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); if (($options{axis} > 0) and ($options{mode} > 0)) { display_axis(); } glColor3f(0.8,0.8,0.8); if ($options{mode} == 1) { display_2d(); } elsif ($options{mode} == 2) { display_3dwire(); } elsif ($options{mode} == 3) { display_3d(); } glFlush(); glutSwapBuffers(); } # PREVIEW sub preview { if (($xres_real) and (($_[0]==0) or ($_[0]==2))) { $options{xres}=$xres_real; $options{zres}=$zres_real; $xres_real=0; $zres_real=0; reset_all(0); } elsif ((!$xres_real) and (($_[0]==1) or ($_[0]==2))) { $xres_real=$options{xres}; $zres_real=$options{zres}; $options{xres}=20; $options{zres}=20; reset_all(0); } elsif (($_[0]==3) and $xres_real) { return 1; } elsif (($_[0]==3) and !$xres_real) { return 0; } } # KEYBOARD sub keyboard { my ($key) = @_; $key = chr($key); # Misc if ($key=~/q/i){ exit(); } elsif($key=~/m/i){ screenshot(); } elsif($key=~/3/i){ $options{cfact}=$options{cfact}*0.98; glutPostRedisplay(); } elsif($key=~/4/i){ $options{cfact}=$options{cfact}*1.02; glutPostRedisplay(); } elsif($key=~/_/i){ reset_all(3); } # Preview elsif($key=~/p/i){ preview(2); } # Function change elsif($key=~/n/i){ $n++; reset_all(0); } elsif(($key=~/b/i) and ($n > 0)){ $n--; reset_all(0); } # Mode change elsif(($key=~/1/i) and ($options{mode}>0)){ $options{mode}--; reset_all(0); } elsif(($key=~/2/i) and ($options{mode}<3)){ $options{mode}++; reset_all(0); } elsif($key=~/c/i) { $options{color}++; if ($options{color} >=3) { $options{color}=0; } glutPostRedisplay(); } elsif($key=~/t/i) { if ($options{time} == 0) { $options{time}=1; } else { $options{time}=0; } } # Seeking elsif($key=~/x/i) { reset_all(0); if (($options{time} > 0) and ($tsize <= ($options{tres}-5))) { $t += 5*($options{tmax}-$options{tmin})/($options{tres}-1); $tsize=$tsize+5; } elsif ($tsize < $options{tres}) { $t += ($options{tmax}-$options{tmin})/($options{tres}-1); $tsize++; } } elsif($key=~/y/i) { reset_all(0); if (($options{time} > 0) and ($tsize >= 5)) { $t -= 5*($options{tmax}-$options{tmin})/($options{tres}-1); $tsize=$tsize-5; } elsif ($tsize > 0) { $t -= ($options{tmax}-$options{tmin})/($options{tres}-1); $tsize--; } } # Resolution elsif($key=~/u/i){ if (preview(3)) { $xres_real=int($xres_real*1.1+0.9); $zres_real=int($zres_real*1.1+0.9); reset_all(0); } else { $options{xres}=int($options{xres}*1.1+0.9); $options{zres}=int($options{zres}*1.1+0.9); reset_all(0); } } elsif($key=~/z/i){ if (preview(3)) { $xres_real=int($xres_real*0.91+0.2); $zres_real=int($zres_real*0.91+0.2); reset_all(0); } else { $options{xres}=int($options{xres}*0.91+0.2); $options{zres}=int($options{zres}*0.91+0.2); reset_all(0); } } elsif($key=~/j/i){ $options{tres}=int($options{tres}*1.1+0.9); reset_all(1); } elsif($key=~/h/i){ $options{tres}=int($options{tres}*0.91+0.2); reset_all(1); } # Rotation elsif($key=~/w/i){ glRotatef(3, 1, 0, 0); glutPostRedisplay(); } elsif($key=~/s/i){ glRotatef(-3, 1, 0, 0); glutPostRedisplay(); } elsif($key=~/a/i){ glRotatef(3, 0, 1, 0); glutPostRedisplay(); } elsif($key=~/d/i){ glRotatef(-3, 0, 1, 0); glutPostRedisplay(); } # Translation elsif($key=~/\ü/i){ glTranslatef(0, 0.5, 0); glutPostRedisplay(); } elsif($key=~/\ä/i){ glTranslatef(0, -0.5, 0); glutPostRedisplay(); } elsif($key=~/\ö/i){ glTranslatef(-0.5, 0, 0); glutPostRedisplay(); } elsif($key=~/\$/i){ glTranslatef(0.5, 0, 0); glutPostRedisplay(); } # Scaling elsif($key=~/r/i){ glScalef(1.1,1.1,1.1); glutPostRedisplay(); } elsif($key=~/e/i){ glScalef(0.91,0.91,0.91); glutPostRedisplay(); } # Position elsif($key=~/0/i){ reset_all(2); } elsif($key=~/9/i){ glRotatef(90,1,0,0); glutPostRedisplay(); } elsif($key=~/8/i){ glRotatef(90,0,1,0); glutPostRedisplay(); } elsif($key=~/7/i){ glRotatef(90,0,0,1); glutPostRedisplay(); } } # USAGE sub usage { print STDERR < \$options{fullscreen}, "nofullscreen|nofs" => sub { $options{fullscreen}=0; }, "geometry=s" => sub { @geometry=split(/[x+]/,"$_[1]") }, "wid=s" => \$options{wid}, "nograph" => sub { $options{mode}=0 }, "2d" => sub { $options{mode}=1 }, "wire|3dwire" => sub { $options{mode}=2 }, "3d|3dsolid" => sub { $options{mode}=3 }, "axis=i" => \$options{axis}, "ax_step=f" => \$options{ax_step}, "ax_size=f" => \$options{ax_size}, "noaxis" => sub { $options{axis}=0 }, "time" => sub { $options{time}=1 }, "notime" => sub { $options{time}=0 }, "colors=i" => \$options{color}, "nocolors" => sub { $options{color}=0 }, "xmin=f" => \$options{xmin}, "xmax=f" => \$options{xmax}, "ymin=f" => \$options{ymin}, "ymax=f" => \$options{ymax}, "zmin=f" => \$options{zmin}, "zmax=f" => \$options{zmax}, "tmin=f" => \$options{tmin}, "xres=i" => \$options{xres}, "zres=i" => \$options{zres}, "xzres=i" => sub { $options{xres}=$_[1];$options{zres}=$_[1]; }, "tres=i" => \$options{tres}, "fps=f" => \$options{fps}, "cfact=f" => \$options{cfact}, "cconst=f" => \$options{cconst}, "o=s" => \$options{image_name}, "help|h" => \&usage, "version|v" => \&version, ) || usage(); # Add command line functions BUGGY @yreal = (@ARGV, @yreal); for (@yreal) { $_ =~ s/(? 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); return($r,$g,$b); } } # IDLE sub idle { # if (tv_interval($time)<(1/50)){ # print "sleep ",tv_interval($time)," \n"; # usleep (1/($options{fps}*5)); # return; # } if ($zsize < $options{zres}) { if ($options{mode} == 1) { idle_2d(); display(); } if ($options{mode} >= 2) { idle_3d(); if ($zsize == $options{zres}) {display();} } } elsif (($options{time} == 1) and ($tsize < ($options{tres}-1))) { reset_all(0); $t += ($options{tmax}-$options{tmin})/($options{tres}-1); $tsize++; } elsif (($options{time} == 2) and ($tsize > 0)) { reset_all(0); $t -= ($options{tmax}-$options{tmin})/($options{tres}-1); $tsize--; } elsif ($options{time} == 1) { $options{time}=2; } elsif ($options{time} == 2) { $options{time}=1; } # $time = [gettimeofday]; # usleep (0.0001) if ($options{time} == 0); } # SUB IDLE (2D) sub idle_2d { my (@tripar,$x,$y,$j,$eval_block); $x=$options{xmin}; $j=0; $eval_block= ' while ($j<=(2*$options{xres}-2)) { '; $eval_block.= "\$y = $yreal[$n];"; $eval_block.= ' $tripar[$j]=$x; $tripar[$j+1]=$y; $x += ($options{xmax}-$options{xmin})/($options{xres}-1); $j=$j+2; } return 1; '; while ($j<=(2*$options{xres}-2)){ last if eval($eval_block); $tripar[$j]=$x; $tripar[$j+1]=0; $x += ($options{xmax}-$options{xmin})/($options{xres}-1); $j=$j+2; } $j = 0; $zsize = $options{zres} + 1; unshift(@tri2d,@tripar); splice(@tri2d,(2*$options{xres})); } # SUB IDLE (3D) sub idle_3d { my (@tripar,$x,$y,$j,$eval_block); $x=$options{xmin}; $j=0; $eval_block=' while ($j<=(3*$options{xres}-3)) { '; $eval_block.= "\$y = $yreal[$n];"; $eval_block.= ' $tripar[$j]=$x; $tripar[$j+1]=$y; $tripar[$j+2]=$z; $x += ($options{xmax}-$options{xmin})/($options{xres}-1); $j=$j+3; } return 1; '; while ($j<=(3*$options{xres}-3)){ last if eval($eval_block); $tripar[$j]=$x; $tripar[$j+1]=0; $tripar[$j+2]=$z; $x += ($options{xmax}-$options{xmin})/($options{xres}-1); $j=$j+3; } $j = 0; $z += ($options{zmax}-$options{zmin})/($options{zres}-1); $zsize++; # IMPORTANT !!!! unshift(@tri3d,@tripar); splice(@tri3d,(9*$options{xres}*$options{zres})); } # SUB DISPLAY (2D) sub display_2d { my $i; glBegin(GL_LINE_STRIP); { if ($options{color} > 0) { glColor3f(scolor($tri2d[1])); } glVertex2f($tri2d[0],$tri2d[1]); for ($i=2; $i<=(2*$options{xres}-2); $i=$i+2) { if ($options{color} > 0) { glColor3f(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); { # first line if ($h==0) { for ($i=(3*$options{xres}-3); $i>=0; $i=$i-3) { if ($options{color} > 0) { glColor3f(scolor($tri3d[$i+1])); } glVertex3f($tri3d[$i],$tri3d[$i+1],$tri3d[$i+2]); } } for ($i=0; $i<=(3*$options{xres}-4); $i=$i+3) { my $basec = $i+1+3*$h*$options{xres}; # left behind if ($options{color} > 0) { glColor3f(scolor($tri3d[$basec])); } glVertex3f($tri3d[$basec-1],$tri3d[$basec],$tri3d[$basec+1]); # left ahead if ($options{color} > 0) { glColor3f(scolor($tri3d[$basec+3*$options{xres}])); } glVertex3f($tri3d[$basec-1+3*$options{xres}],$tri3d[$basec+3*$options{xres}],$tri3d[$basec+1+3*$options{xres}]); # rigth ahead if ($options{color} > 0) { glColor3f(scolor($tri3d[$basec+3+3*$options{xres}])); } glVertex3f($tri3d[$basec+2+3*$options{xres}],$tri3d[$basec+3+3*$options{xres}],$tri3d[$basec+4+3*$options{xres}]); } # right behind if ($options{color} > 0) { glColor3f(scolor($tri3d[3*$options{xres}-2+3*$h*$options{xres}])); } glVertex3f($tri3d[3*$options{xres}-3+3*$h*$options{xres}],$tri3d[3*$options{xres}-2+3*$h*$options{xres}],$tri3d[3*$options{xres}-1+3*$h*$options{xres}]); # right ahead if ($options{color} > 0) { glColor3f(scolor($tri3d[3*$options{xres}-2+3*$h*$options{xres}+3*$options{xres}])); } glVertex3f($tri3d[3*$options{xres}-3+3*$h*$options{xres}+3*$options{xres}],$tri3d[3*$options{xres}-2+3*$h*$options{xres}+3*$options{xres}],$tri3d[3*$options{xres}-1+3*$h*$options{xres}+3*$options{xres}]); } glEnd(); } } # SUB DISPLAY (3D SOLID) sub display_3d { my ($h,$i); glBegin(GL_TRIANGLES); { for $h (0..($zsize-2)) { for ($i=0; $i<=(3*$options{xres}-4); $i=$i+3) { my $basec = $i+1+3*$h*$options{xres}; my @ltcolor; my @rbcolor; # left bottom if ($options{color} > 0) { glColor3f(scolor($tri3d[$basec])); } glVertex3f($tri3d[$basec-1],$tri3d[$basec],$tri3d[$basec+1]); # left top if ($options{color} > 0) { @ltcolor=scolor($tri3d[$basec+3*$options{xres}]); glColor3f(@ltcolor) } glVertex3f($tri3d[$basec+3*$options{xres}-1],$tri3d[$basec+3*$options{xres}],$tri3d[$basec+3*$options{xres}+1]); # right bottom if ($options{color} > 0) { @rbcolor=scolor($tri3d[$basec+3]);glColor3f(@rbcolor);} glVertex3f($tri3d[$basec+2],$tri3d[$basec+3],$tri3d[$basec+4]); # left top if ($options{color} > 0) { glColor3f(@ltcolor);} glVertex3f($tri3d[$basec+3*$options{xres}-1],$tri3d[$basec+3*$options{xres}],$tri3d[$basec+3*$options{xres}+1]); # right top if ($options{color} > 0) { glColor3f(scolor($tri3d[$basec+3*$options{xres}+3])); } glVertex3f($tri3d[$basec+3*$options{xres}+2],$tri3d[$basec+3*$options{xres}+3],$tri3d[$basec+3*$options{xres}+4]); # right bottom if ($options{color} > 0) { glColor3f(@rbcolor); } glVertex3f($tri3d[$basec+2],$tri3d[$basec+3],$tri3d[$basec+4]); } } } glEnd(); } # SUB DISPLAY (AXIS) sub display_axis { my $i; glColor3f(0.3,0.3,0.3); if ($options{axis} == 1) { if ($options{mode} <= 1) { # 2D axis glBegin(GL_LINES); { for ($i=0; $i<=($options{xmax}); $i=$i+$options{ax_step}) { glVertex2f($i,(0-($options{ymax}-$options{ymin})*$options{ax_size}/2)); glVertex2f($i,(0+($options{ymax}-$options{ymin})*$options{ax_size}/2)); } for ($i=0; $i>=($options{xmin}); $i=$i-$options{ax_step}) { glVertex2f($i,(0-($options{ymax}-$options{ymin})*$options{ax_size}/2)); glVertex2f($i,(0+($options{ymax}-$options{ymin})*$options{ax_size}/2)); } for ($i=0; $i<=($options{ymax}); $i=$i+$options{ax_step}) { glVertex2f((0-($options{xmax}-$options{xmin})*$options{ax_size}/2),$i); glVertex2f((0+($options{xmax}-$options{xmin})*$options{ax_size}/2),$i); } for ($i=0; $i>=($options{ymin}); $i=$i-$options{ax_step}) { glVertex2f((0-($options{xmax}-$options{xmin})*$options{ax_size}/2),$i); glVertex2f((0+($options{xmax}-$options{xmin})*$options{ax_size}/2),$i); } glColor3f(0.4,0.4,0.4); glVertex2f($options{xmin},0); glVertex2f($options{xmax},0); glVertex2f(0,$options{ymin}); glVertex2f(0,$options{ymax}); } glEnd(); } else { # 3D axis glBegin(GL_LINES); { for ($i=0; $i<=($options{xmax}); $i=$i+$options{ax_step}) { glVertex3f($i,0,(0-($options{zmax}-$options{zmin})*$options{ax_size}/2)); glVertex3f($i,0,(0+($options{zmax}-$options{zmin})*$options{ax_size}/2)); } for ($i=0; $i>=($options{xmin}); $i=$i-$options{ax_step}) { glVertex3f($i,0,(0-($options{zmax}-$options{zmin})*$options{ax_size}/2)); glVertex3f($i,0,(0+($options{zmax}-$options{zmin})*$options{ax_size}/2)); } for ($i=0; $i<=($options{zmax}); $i=$i+$options{ax_step}) { glVertex3f((0-($options{xmax}-$options{xmin})*$options{ax_size}/2),0,$i); glVertex3f((0+($options{xmax}-$options{xmin})*$options{ax_size}/2),0,$i); } for ($i=0; $i>=($options{zmin}); $i=$i-$options{ax_step}) { glVertex3f((0-($options{xmax}-$options{xmin})*$options{ax_size}/2),0,$i); glVertex3f((0+($options{xmax}-$options{xmin})*$options{ax_size}/2),0,$i); } glColor3f(0.4,0.4,0.4); glVertex3f($options{xmin},0,0); glVertex3f($options{xmax},0,0); glVertex3f(0,$options{ymin},0); glVertex3f(0,$options{ymax},0); glVertex3f(0,0,$options{zmin}); glVertex3f(0,0,$options{zmax}); } glEnd(); } } elsif ($options{axis} == 2) { # Base square glBegin(GL_LINES); { glVertex3f($options{xmin},0,$options{zmin}); glVertex3f($options{xmax},0,$options{zmin}); glVertex3f($options{xmin},0,$options{zmin}); glVertex3f($options{xmin},0,$options{zmax}); glVertex3f($options{xmin},0,$options{zmax}); glVertex3f($options{xmax},0,$options{zmax}); glVertex3f($options{xmax},0,$options{zmax}); glVertex3f($options{xmax},0,$options{zmin}); } glEnd(); } elsif ($options{axis} == 3) { # Base cube glBegin(GL_LINES); { #bottom square glVertex3f($options{xmin},$options{ymin},$options{zmin}); glVertex3f($options{xmax},$options{ymin},$options{zmin}); glVertex3f($options{xmin},$options{ymin},$options{zmin}); glVertex3f($options{xmin},$options{ymin},$options{zmax}); glVertex3f($options{xmin},$options{ymin},$options{zmax}); glVertex3f($options{xmax},$options{ymin},$options{zmax}); glVertex3f($options{xmax},$options{ymin},$options{zmax}); glVertex3f($options{xmax},$options{ymin},$options{zmin}); #between glVertex3f($options{xmin},$options{ymin},$options{zmin}); glVertex3f($options{xmin},$options{ymax},$options{zmin}); glVertex3f($options{xmin},$options{ymin},$options{zmax}); glVertex3f($options{xmin},$options{ymax},$options{zmax}); glVertex3f($options{xmax},$options{ymin},$options{zmin}); glVertex3f($options{xmax},$options{ymax},$options{zmin}); glVertex3f($options{xmax},$options{ymin},$options{zmax}); glVertex3f($options{xmax},$options{ymax},$options{zmax}); #top square glVertex3f($options{xmin},$options{ymax},$options{zmin}); glVertex3f($options{xmax},$options{ymax},$options{zmin}); glVertex3f($options{xmin},$options{ymax},$options{zmin}); glVertex3f($options{xmin},$options{ymax},$options{zmax}); glVertex3f($options{xmin},$options{ymax},$options{zmax}); glVertex3f($options{xmax},$options{ymax},$options{zmax}); glVertex3f($options{xmax},$options{ymax},$options{zmax}); glVertex3f($options{xmax},$options{ymax},$options{zmin}); } glEnd(); } # # x,y,z rays # glBegin(GL_LINES); { # glVertex3f(0,0,0); # glVertex3f($options{xmax},0,0); # glVertex3f(0,0,0); # glVertex3f(0,$options{ymax},0); # glVertex3f(0,0,0); # glVertex3f(0,0,$options{zmax}); # } glEnd(); # # x,y,z lines # glBegin(GL_LINES); { # glVertex3f($options{xmin},0,0); # glVertex3f($options{xmax},0,0); # glVertex3f(0,$options{ymin},0); # glVertex3f(0,$options{ymax},0); # glVertex3f(0,0,$options{zmin}); # glVertex3f(0,0,$options{zmax}); # } glEnd(); } # 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); #height $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 "$options{image_name}_$num.bmp"); if(open(IMAGE,">$options{image_name}_$num.bmp")){ print IMAGE getheader($options{width},$options{height}); my @pixels=glReadPixels_p(0, 0,$options{width},$options{height},GL_RGB,GL_UNSIGNED_INT); 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); } close(IMAGE); } }