#!/usr/add-on/exptools_build/test_version/install/perl5/bin/perl
# simple maze thingy


#BEGIN {print STDERR "quest.wri: starting up now $!\n";}
#END {print STDERR "quest.wri: exiting now $!\n";}
BEGIN{ unshift(@INC,"./blib"     ); unshift(@INC,"../blib"     ); }
BEGIN{ unshift(@INC,"./blib/lib" ); unshift(@INC,"../blib/lib" ); }
BEGIN{ unshift(@INC,"./blib/arch"); unshift(@INC,"../blib/arch"); }
use OpenGL;
 
 
 @walldata = (
 	"****************",
 	"* *     *      *",
 	"* * *** * *    *",
 	"* *   * ** * * *",
 	"*   * *      * *",
 	"********** *** *",
 	"*           *  *",
 	"* ***** *** ****",
 	"* *   *   *    *",
 	"*   * *** *    *",
 	"* *   *   *  * *",
 	"* ***** **** * *",
 	"*     *      * *",
 	"***** ******** *",
 	"*   * *     *  *",
 	"* ***   *** ****",
 	"*     *   *    *",
 	"****************",
 	);
 
 
 $x_size = scalar(@walldata);
 $y_size = length($walldata[0]);
 ($x_size > 3 && $x_size<200) || die "bad data - number of rows $x_size ";
 ($y_size > 3 && $y_size<200) || die "bad data - number of columns $y_size ";
 
 
 	for($x=0;$x<$x_size;$x++) {
 		($y_size==length($walldata[$x])) || 
 		    die "line $x of data ",length($walldata[$x]),"/$y_size chars";
 		$walldata[$x] =~ s/ /0/g;
 		$walldata[$x] =~ s/\*/1/g;
 		my(@ww)=split(//,$walldata[$x]);
 		#print "$wall[$x] - @ww -";
 		$wall[$x] = \ @ww;
 		#print "@{$wall[$x]}\n";
 	}
 	$s=1;
     	@cx=(0,0,0,0,$s,$s,$s,$s);
     	@cy=(0,0,$s,$s,0,0,$s,$s);
     	@cz=(0,$s,$s,0,0,$s,$s,0);
     	@cf=( 
         	0, 1, 2, 3,
         	3, 2, 6, 7,
         	7, 6, 5, 4,
         	4, 5, 1, 0,
         	5, 6, 2, 1,
         	7, 4, 0, 3,
            );
     @r=(0.5, 0,   0,   0.5, 1.0, 0);
     @g=(0,   0.5, 0,   0.5, 0,   1.0);
     @b=(0,   0,   0.5, 0,   1.0, 1.0);
 
 sub drawwalls {
 	local($x,$y,$dl);
 	glNewList($dl=glGenLists(1),GL_COMPILE);
 	for($x=0;$x<$x_size;$x++) {
 		for($y=0;$y<$y_size;$y++) {
 			if($wall[$x]->[$y]) {
     				for($i=0;$i<6;$i++){
 					if(
 					   $i==4 || $i==5 || 
 						  ($i==0 && ($x==0  || !($wall[$x-1]->[$y]))) || 
 						  ($i==1 && ($y==$y_size-1 || !($wall[$x]->[$y+1]))) ||
 						  ($i==2 && ($x==$x_size-1 || !($wall[$x+1]->[$y]))) ||
 						  ($i==3 && ($y==0  || !($wall[$x]->[$y-1]))) 
 						 ) {
 						glColor3f($r[$i],$g[$i],$b[$i]);
  						glBegin(GL_POLYGON);
 						#print " begin poly $x,$y  $i\n";
         					for($j=0;$j<4;$j++){
                 					$k=$cf[$i*4+$j];
                 					glVertex3d($x+$cx[$k],$y+$cy[$k],$cz[$k]);
 					        }
 						glEnd();
 					}
 				}
 			}
 		}
 	}
 	glColor3f(0,1,0);
 	glBegin(GL_POLYGON);
 	glVertex3f(1+0.2,1+0.2,0);
 	glVertex3f(1+0.2,1+0.8,0);
 	glVertex3f(1+0.8,1+0.8,0);
 	glVertex3f(1+0.8,1+0.2,0);
 	glEnd();
 
 	glColor3f(1,0,0);
 	glBegin(GL_POLYGON);
 	glVertex3f($x_size-2+0.2,$y_size-2+0.2,0);
 	glVertex3f($x_size-2+0.2,$y_size-2+0.8,0);
 	glVertex3f($x_size-2+0.8,$y_size-2+0.8,0);
 	glVertex3f($x_size-2+0.8,$y_size-2+0.2,0);
 	glEnd();
 
 	glEndList();
 	$dl;
 }
 
 
 
 
 sub intro {
   # give a cool intro to the thing
   # spin the maze around on 2 axis then
   # zoom in to the starting position.
   local($spin,$p);
   $spin=360*2;
   while($spin-=5) {
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     glLoadIdentity();
     glPushMatrix();
     glTranslatef(0,0,-20);
     glRotatef($spin, 0.0, 1.0, 1.0);
     glTranslatef(-$x_size/2,-$y_size/2,0);
     glCallList($walls);
     glPopMatrix();
     glXSwapBuffers;
   }
   for($p=0 ; $p <= 1 ; $p+=0.02) {
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     glLoadIdentity();
     glPushMatrix();
     glRotatef(-90*$p,1,0,0);
 
     glRotatef($b*$p,0,0,1);
 
     glTranslatef(-$x*$p + -$x_size/2*(1-$p),-$y*$p+ -$y_size/2*(1-$p),-0.5*$p + -20*(1-$p));
 
     glCallList($walls);
     glPopMatrix();
     glXSwapBuffers;
   }
 }
 
 $x=1.5 ; $y=1.5 ; $b = 90 ;
 
 sub forward {
 	# this routine does wall collision detection
 	# the inputs to this routine are:
 	#         - the current location
 	#         - the desired location 
 	#         - the minimum distance to wall allowed 
 	# returns
 	#         - new coordinates after move
 	#         - whether a wall caused change in target position
 	# This is really easy with these walls that lie only on axes.
 	local($x,$y,$px,$py, $bf) = @_;
 	local($h)=(0);
 	if($px>int($x)+1.0-$bf && $wall[$x+1]->[$y]) {
 		$px = int($x)+1.0-$bf;
 		$h++;
 	}
 	if($py>int($y)+1.0-$bf && $wall[$x]->[$y+1]) {
 		$py = int($y)+1.0-$bf;
 		$h++;
 	}
 	if($px<int($x)+$bf && $wall[$x-1]->[$y]) {
 		$px = int($x)+$bf;
 		$h++;
 	}
 	if($py<int($y)+$bf && $wall[$x]->[$y-1]) {
 		$py = int($y)+$bf;
 		$h++;
 	}
 	($px,$py,$h);
 }
 sub abs {
 	($_[0] > 0) ? $_[0] : - $_[0];
 }
 
 sub nav {
     # routine for navigating through the maze
     $t++;
     ($px,$py,$pm) = glpXQueryPointer;
     if ($pm & Button1Mask) { $b -= ( $pm & (ShiftMask)) ?9 :3; }  
     if ($pm & Button3Mask) { $b += ( $pm & (ShiftMask)) ?9 :3; }  
     if ($pm & Button2Mask) { 
 	$speed = ( $pm & (ShiftMask)) ?0.15 : 0.05;
 	($x,$y) = forward($x,$y,$x+$speed*sin($b*3.14/180),
 				$y+$speed*cos($b*3.14/180),0.2);  
     } 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     glLoadIdentity();
     glPushMatrix();
     glRotatef(-90,1,0,0);
     glRotatef($b,0,0,1);
     glTranslatef(-$x,-$y,-0.5);
     glCallList($walls);
     # make copy of list since it may get modified during list traversal
     glPopMatrix();
     glXSwapBuffers;
 }
 
 
 
glpOpenWindow(parent, $Plugin::brinfo{xwindow_id}, attributes => [GLX_GREEN_SIZE, 1,GLX_RGBA,GLX_DOUBLEBUFFER]);
 
 glNewList($shot=3,GL_COMPILE);
 glColor3f(0.5,1.0,0.5);
 glBegin(GL_POLYGON);
  glNormal3f( 0.10,   0.0,  0.0);
  glVertex3f( 0.0 ,  0.03, -0.04);
  glVertex3f(  0.0030 , -0.01, -0.04);
  glVertex3f( -0.0030 , -0.01, -0.04);
 glEnd();
 glEndList();
 glNewList($smash=4,GL_COMPILE);
 glColor3f(1.0,0.5,0);
 glBegin(GL_POLYGON);
  glNormal3f( 0.10,   0.0,  0.0);
  glVertex3f( -0.05 ,  0, -0.02);
  glVertex3f( 0.05 ,  0, -0.02);
  glVertex3f(  0.05 ,0, -0.06);
  glVertex3f( -0.05 ,0, -0.06);
 glEnd();
 glEndList();
 
 glEnable(GL_DEPTH_TEST);
 glClearColor(0,0,0,1);
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
     gluPerspective(60.0, 1.0 , 0.1, 60.0); 
     glMatrixMode(GL_MODELVIEW);
 glLoadIdentity ();
 
 $walls=drawwalls;
 
 intro;
 
nav;
while(1){nav;}
