program fourXfourXfour_grid;

uses crt,graph,fin;

const num=100;{number of pixels to make grid}

var pixel:array[1..num] of record
                           x,y,z:real;
                          end;
    pcos,ncos,psin,nsin:real;
    c:char;
    page:byte;
    h,v:integer;

procedure rotx(dir:byte);
var y1,z1:real;
    i:integer;
begin
 for i:=1 to num do
  begin
   if dir=1 then
    begin
     y1:=pcos*pixel[i].y-psin*pixel[i].z;
     z1:=psin*pixel[i].y+pcos*pixel[i].z;
    end
    else
    begin
     y1:=ncos*pixel[i].y-nsin*pixel[i].z;
     z1:=nsin*pixel[i].y+ncos*pixel[i].z;
    end;
   pixel[i].y:=y1;
   pixel[i].z:=z1;
  end;
end;

procedure roty(dir:byte);
var x1,z1:real;
    i:integer;
begin
 for i:=1 to num do
  begin
   if dir=1 then
    begin
     x1:=pcos*pixel[i].x-psin*pixel[i].z;
     z1:=psin*pixel[i].x+pcos*pixel[i].z;
    end
    else
    begin
     x1:=ncos*pixel[i].x-nsin*pixel[i].z;
     z1:=nsin*pixel[i].x+ncos*pixel[i].z;
    end;
   pixel[i].x:=x1;
   pixel[i].z:=z1;
  end;
end;

procedure rotz(dir:byte);
var x1,y1:real;
    i:integer;
begin
 for i:=1 to num do
  begin
   if dir=1 then
    begin
     y1:=pcos*pixel[i].y-psin*pixel[i].x;
     x1:=psin*pixel[i].y+pcos*pixel[i].x;
    end
    else
    begin
     y1:=ncos*pixel[i].y-nsin*pixel[i].x;
     x1:=nsin*pixel[i].y+ncos*pixel[i].x;
    end;
   pixel[i].x:=x1;
   pixel[i].y:=y1;
  end;
end;

procedure eyeview(x,y,z:real;var nx,ny:integer);
const zeye=-300;
begin
 nX:=320+round(x*(Zeye/(Zeye-z)));
 nY:=200+round(y*(Zeye/(Zeye-z)));
end;

procedure display_box;
var i,x,y,x1,y1:integer;
begin
 setactivepage(page);
 delay(10);
 cleardevice;
 if pixel[13].z>pixel[96].z then i:=num-1;
 if pixel[96].z>=pixel[13].z then i:=1;
 repeat
  if i mod 5<>0 then
   begin
    eyeview(pixel[i].x,pixel[i].y,pixel[i].z,x,y);
    eyeview(pixel[i+1].x,pixel[i+1].y,pixel[i+1].z,x1,y1);
    setcolor(trunc(8-pixel[i].z/17)+1);
    line(x,y,x1,y1);
    if i<num-19 then
     begin
      eyeview(pixel[i+20].x,pixel[i+20].y,pixel[i+20].z,x1,y1);
      line(x,y,x1,y1);
     end
   end;
   if((i mod 5=0)and(i<84))then
    begin
     eyeview(pixel[i].x,pixel[i].y,pixel[i].z,x,y);
     eyeview(pixel[i+20].x,pixel[i+20].y,pixel[i+20].z,x1,y1);
     setcolor(trunc(8-pixel[i].z/17)+1);
     line(x,y,x1,y1);
    end;
   if pixel[13].z>pixel[96].z then i:=i-1;
   if pixel[96].z>=pixel[13].z then i:=i+1;
 until i in[num,0];
 setvisualpage(page);
 page:=1-page;
end;

procedure init;
const col:array[1..15]of byte=(1,2,3,4,5,20,7,56,57,58,59,60,61,62,63);
var gd,gm,i:integer;
    x,y,z,angle:real;
begin
 initmouse;
 gd:=9;
 gm:=1;
 initgraph(gd,gm,'');
 randomize;
 x:=-75;
 y:=-75;
 z:=-75;
 for i:=1 to num do
  begin
   pixel[i].x:=x;
   pixel[i].y:=18.75+y*1.2;
   pixel[i].z:=z;
   x:=x+37.5;
   if x=112.5 then
    begin
     x:=-75;
     y:=y+37.5
    end;
   if y=75 then
    begin
     y:=-75;
     z:=z+37.5;
    end;
  end;
 for i:=1 to 15 do setrgbpalette(col[i],0,i*4,0);
 page:=1;
 setactivepage(page);
 display_box;
end;

procedure workout(r:integer);
begin
 pcos:=cos(r div 3*2*pi/360);
 ncos:=cos(-r div 3*2*pi/360);
 psin:=sin(r div 3*2*pi/360);
 nsin:=sin(-r div 3*2*pi/360);
end;

begin
 init;
 repeat
  display_box;
  repeat
   if rclick then
    repeat
     display_box;
     mousemove(h,v);
     if h<0 then begin workout(-h);rotz(1);end;
     if h>0 then begin workout(h);rotz(0);end;
    until rrelease;
   mousemove(h,v);
   if v<0 then begin workout(v);rotx(1);end;
   if v>0 then begin workout(-v);rotx(0);end;
   if h<0 then begin workout(h);roty(1);end;
   if h>0 then begin workout(-h);roty(0);end;
  until(h<>0)or(v<>0);
 until lclick;
 closegraph;
end.
