{$N+,A+,G+,F+,D-,E-,L-,R-,S-,Q-,Y-}
unit tunnel;
interface

procedure init_tunnel;
procedure scene_tunnel;

implementation
uses triangle, circles, global, resource, screen, palette, memory, math2;

const
cubic: array[0..23] of shortint = (
    -1, -1, -1,
    1, -1, -1,
    1, 1, -1,
    -1, 1, -1,
    -1, -1, 1,
    1, -1, 1,
    1, 1, 1,
    -1, 1, 1);

pindexc:array[0..35] of byte =(
    0, 1, 2, 0, 2, 3,
    1, 5, 6, 1, 6, 2,
    5, 4, 7, 5, 7, 6,
    4, 0, 3, 4, 3, 7,
    3, 2, 6, 3, 6, 7,
    4, 5, 1, 4, 1, 0);


var
cubeDc:array[0..23] of single;


procedure drawcubic(xx,yy:integer; bright:single; outp : word);
var
x1,x2,x3,x4,y1,y2,y3:integer;
col, p,p3:integer;
sqrt_s, pom, ax,ay,az,bx,by,bz,nx,ny,nz:single;
begin
 p3:=0;
 for p:=0 to 11 do begin
  ax:=cubeDc[pindexc[p3+2]*3]  -cubeDc[pindexc[p3]*3];
  ay:=cubeDc[pindexc[p3+2]*3+1]-cubeDc[pindexc[p3]*3+1];
  az:=cubeDc[pindexc[p3+2]*3+2]-cubeDc[pindexc[p3]*3+2];
  bx:=cubeDc[pindexc[p3+1]*3]  -cubeDc[pindexc[p3]*3];
  by:=cubeDc[pindexc[p3+1]*3+1]-cubeDc[pindexc[p3]*3+1];
  bz:=cubeDc[pindexc[p3+1]*3+2]-cubeDc[pindexc[p3]*3+2];
  nx:=ay*bz-az*by;
  ny:=az*bx-ax*bz;
  nz:=ax*by-ay*bx;
  pom:=nz*-4+nx*ax+ny*ay+nz*az;

  if (pom>0) then begin

     x1:=round(cubeDc[pindexc[p3]*3])+xx;
     y1:=round(cubeDc[pindexc[p3]*3+1])+yy;
     {z1:=round(cubeDc[pindexc[p*3]*3+2])+zz;}
     x3:=round(cubeDc[pindexc[p3+1]*3])+xx;
     y3:=round(cubeDc[pindexc[p3+1]*3+1])+yy;
     {z3:=round(cubeDc[pindexc[p*3+1]*3+2])+zz;}
     x2:=round(cubeDc[pindexc[p3+2]*3])+xx;
     y2:=round(cubeDc[pindexc[p3+2]*3+1])+yy;
     {z2:=round(cubeDc[pindexc[p*3+2]*3+2])+zz;}

     if bright<0 then bright:=0;
     if bright>61 then bright:=61;
     sqrt_s:=sqrt_(nx*nx+ny*ny+nz*nz);
     col:=round((nz*-4)/(sqrt_s*4)*bright)+1;{}
     Triangle_asm(x1,y1,x2,y2,x3,y3,col, outp);{}
   end;

 p3:=p3+3;
 end;
end;


procedure rotateCubic(xr,yr,zr, scalec, per:single);
var x,y,z,X1,Y1,Z1:single;
Cosxan,Sinxan,Cosyan,Sinyan,Coszan,Sinzan:single;
p,p3:integer;
begin
CosXan:=cos(Xr);SinXan:=sin(Xr);
CosYan:=cos(Yr);SinYan:=sin(Yr);
CosZan:=cos(Zr);SinZan:=sin(Zr);
p3:=0;
 for p:=0 to 7 do begin
  x:=cubic[p3];
  y:=cubic[p3+1];
  z:=cubic[p3+2];
  x1:=cosyan*x-sinyan*z;
  z1:=sinyan*x+cosyan*z;
  x:=coszan*x1+sinzan*y;
  y1:=coszan*y-sinzan*x1;
  z:=cosxan*z1-sinxan*y1;
  y:=sinxan*z1+cosxan*y1;
  CubeDc[p3]:=(x*per/(z-per)*scalec);
  CubeDc[p3+1]:=(y*per/(z-per)*scalec);
  CubeDc[p3+2]:=(-z*per/(z-per)*scalec);
  p3:=p3+3;
end;
end;



var
stage:byte;
speed_palette, obj_goon, q,n:word;
r,g,b,p,m,d:integer;
tunnel_cut, x,y,size2, size,count_dots, col:integer;
Aantal, T1,start_time,old_time, current_time, elapsed_time:word;
min_d, max_d:word;
v50, v04, x_const,y_const, zigzag, TAU, camZ, cam_x,cam_y, tun_x, tun_y, pz:single;
j_cub, obj_z, tun, dd, xx,yy, a:single;

procedure init_tunnel;
begin
{for n:=0 to 64 do PrecalsCircle(n, vaddr2);}

TAU:=6.283185307;
x_const:=0.64543324;
y_const:=0.38457832;

v04:=0.4;
v50:=50;
zigzag:=0;
max_d:=16;
count_dots:=12;

tun:=1024/count_dots;

tunnel_cut:=0;

obj_z:=0;
obj_goon:=0;
stage:=0;

for n:=0 to 1023 do begin
a:=cos(6.283185307/1024 *n -1.3);
meml[vaddr3:n shl 2]:=longint(a);
a:=sin(6.283185307/1024 *n -1.3);
meml[vaddr3:4096+ n shl 2]:=longint(a);
end;

if useXMS=1 then begin
    LoadBufferToXMS('tunnel3', 8192,  vaddr3);
end;

end;





procedure scene_tunnel;
begin
Clear(0, 65535, vaddr);
Clear(0, 65535, vaddr2);
Clear(0, 65535, vaddr3);
if useXMS=1 then begin
   LoadBufferFromXMS('tunnel3', vaddr3, 0);
end else init_tunnel;

LoadBinUnpack('circles.bin',  {load->}vaddr,{-unpack->}vaddr2,  0);



for n:=0 to 255 do setonecolor2memw(n, 5,5,12, palette1, seg_palitra,ofs_palitra);

r:=5; g:=5; b:=12;
for n:=1 to 63 do begin
m:=n;
p:=n shr 1;
setonecolor2memW(n,r+p,g+p,b+p, palette2, seg_palitra,ofs_palitra);
setonecolor2memW(n+64,r+m shr 1,g+m shr 3,b+m shr 2, palette2, seg_palitra,ofs_palitra);

setonecolor2memW(n+128,r+p,g+p,b+p, palette2, seg_palitra,ofs_palitra);
setonecolor2memW(n+192,r+m shr 3, g+m shr 3, round(b+m/1.5), palette2, seg_palitra,ofs_palitra);
end;

setonecolor2memw(0, 0,0,0, palette2, seg_palitra,ofs_palitra);

init_pal2pal(seg_palitra,ofs_palitra);
palette_process[0]:=1;
palette_process[1]:=1;
speed_palette:=4;

setpalette_from_memW(palette1,seg_palitra,ofs_palitra);

old_time:=mtimer;
start_time:=mtimer;
Aantal:=0; T1:=mTimer;

repeat

elapsed_time:=(mtimer-old_time);
old_time:=mtimer;

q:=mtimer-start_time;
camZ:=q/70;

{-----------------------------------------------------------------}
if (elapsed_time>0) or (aantal=0) then begin

MP^.GetInformation(@info); {midas get info);}

if (stage=0) and (zigzag<0.4) then zigzag:=zigzag+elapsed_time/700;

if (stage=0) and music_pos(18,32) then stage:=1;


if (stage=1) and (zigzag>0.1) then zigzag:=zigzag-elapsed_time/700;

if (stage=1) and music_pos(19,32) then stage:=2;


if (stage=2) then begin
    for n:=1 to 255 do setonecolor2memW(n,50,50,50, palette2, seg_palitra,ofs_palitra);
    init_pal2pal(seg_palitra,ofs_palitra);
    speed_palette:=16;
    inc(stage);
end;

if (stage>=3) then begin {start cubic}
    if obj_goon<160 then obj_goon:=obj_goon+elapsed_time;{}
    if (stage=3) and (obj_goon>60) then begin inc(stage); palette_process[0]:=1; palette_process[1]:=1; end;
end;

end;{-----------------------------------------------------------------}

Clear(1, 64000, vaddr);{}


for d:=1 to max_d do begin
pz:= 1 - d / max_d;
a:=round(camZ / (4/max_d));
a:=a*(4/max_d);
a:=CamZ - a;
pz:= pz - a;

{---Call center coord of circle----}

cam_x:=zigzag*sin_(TAU * camZ * x_const);
cam_y:=zigzag*cos_(TAU * camZ * y_const);
tun_x:=zigzag*sin_(TAU * (camZ+pz) * x_const);
tun_y:=zigzag*cos_(TAU * (camZ+pz) * y_const);
xx := (tun_x - cam_x) *160+160;
yy := (tun_y - cam_y) *100+100;

tun_x:=(tun_x - cam_x)*8;
tun_y:=(tun_y - cam_y)*8;

{diametr}
dd:= pz + 0.4;
dd:= dd * dd;
dd:= 50/dd;
{color}
col:=round((1-pz)*42);
if col>63 then col:=63;
if col<1 then col:=1;

col:=col+ (d and 1)*128;

size:=round(dd / 5);
if size>60 then size:=60;
if size<1 then size:=1;
size2:=size shr 2;


for n:=tunnel_cut to count_dots-1 -tunnel_cut do begin

x:= round(xx + single( meml[vaddr3:( round(n*85+tun_x*10)      and 1023) shl 2 ] ) *dd);
y:= round(yy + single( meml[vaddr3:4096+( round(n*85+tun_x*10) and 1023) shl 2 ] ) *dd);

if (size>2) and (x>size) and (x<320-size) then
FillCircle5_without_cut(x,y, size , byte(col+64), vaddr2, vaddr)
else FillCircle5(x,y, size , byte(col+64), vaddr2, vaddr);{}

x:=round(x+tun_x);
y:=round(y+tun_y);
if (size2>2) and (x>size2) and (x<320-size2) then
FillCircle5_without_cut(x,y, size2 , byte(col), vaddr2, vaddr)
else FillCircle5(x,y, size2 , byte(col+128), vaddr2, vaddr);

end;
end;

{----------------------------------------------------------------------}
if obj_goon>0 then begin
   obj_z:=  obj_goon / 128;
   a:=(camZ / (4/128));
   a:=a*(4/128);
   a:=CamZ - a;
   obj_z:= obj_z - a;

   cam_x:=zigzag*sin_(TAU * camZ * x_const);
   cam_y:=zigzag*cos_(TAU * camZ * y_const);
   tun_x:=zigzag*sin_(TAU * (camZ+obj_z) * x_const);
   tun_y:=zigzag*cos_(TAU * (camZ+obj_z) * y_const);
   xx := (-tun_x) *50+175;
   yy := (tun_y) *50+100;
   {diametr}
   dd:= obj_z + 0.4;
   dd:= dd * dd;

   j_cub:=dd*50;
   rotateCubic(rad(obj_goon*8),rad(obj_goon*2),0, dd*50, -8);
   drawcubic(round(xx),round(yy-abs(cos(obj_goon/12)*j_cub)), dd*40, vaddr);
end;
{----------------------------------------------------------------------}


if Vsync_mode=1 then Midas_WaitVR;{}


   if Aantal and 1 = 0 then
   begin
      if palette_process[0]=1 then
      Pal2Pal_asm(palette_process[0], 1, 108, elapsed_time*speed_palette, seg_palitra,ofs_palitra)
   end
   else begin
      if palette_process[1]=1 then
      Pal2Pal_asm(palette_process[1], 128, 232, elapsed_time*speed_palette, seg_palitra,ofs_palitra);
   end;


FlipScreen(vaddr, vga);

Inc(Aantal);
if FPS_Mode=1 then WriteFps(60, mtimer, T1, Aantal, vga);

until (esc_test) or ((stage=4) and (palette_process[0]=0) and (palette_process[1]=0));

end;

end.