%begin
!!%include "ram_1:graph.inc"
!!%include "ram_1:poly2"
%include "inc:util.imp"
%include "iff:graphinc.imp"
%include "ram_1:random.inc"
%const %real PI = 3.141592653589793238462643
%external%real%fn%spec SIN(%real x)
%external%real%fn%spec COS(%real x)
%const %byte XY = 0, XZ = 1, YZ = 2                    {** View Plane consts **}
%const %integer Max Poly = 100
%constinteger Max Stars = 100
%short %array Stars (1:Max Stars,1:2)
%short OX, OY, MX = -1, MY = -1
%integer StB,StT
%record %format Pt  (%real X, Y, Z)                {** Standard Point Format **}
%record %format IPt (%short X, Y, Z)               {**  Integer Point Format **}
%record %format Polt (%short Num, Depth, %record (Pt) %array V (1:8))
%record (Pt) %array %name Pv (1:8)
%record (Polt) %name %array PL (0: Max Poly)  {** Polygon pointers **}
%record (Polt) %array P1,P2 (0: Max Poly)
%record (Polt) %name Pp
%const %short Ambient = 6, LineDist = 199
%short xp,yp,An = 10
%const %real Rad = Pi/180
%const %byte True = 1, False = 0
%byte Shading = True, Shade Line = False, Hidden = True, Change = True
%byte Moving = False
%real A,Sc, Max,Len
%short xv, yv, zv
%integer Num Ships
%record %format SF (%short CX, CY, Dist, %real CsX, CsY, CsZ, SnX, SnY, SnZ)
%record (SF) %array SRec (1:40)
%record (SF) %name Sp
%record (Pt) Light
%integer CX,CY
%short DS = 0
%real Lx = 10, Ly = -10, Lz = -10, sa, ca
%integer ships,ii,i,j,k,NumPoly
%byte MB

%byte %fn Get Mouse
%byte M,N
%integer i
   %cycle
      M = Mouse Buttons
      N = Mouse Buttons %for i = 1,1,2000
   %repeat %until M = N
   %result = M
%end

%routine Convert
   OX = MX; OY = MY
   MX = (MouseX//3) & 1023
   MY = (MouseY//3) & 1023
%end

%routine Rotate (%byte Plane, %record (Pt) %array (1) %name V, %short Num,
                 %real SinTheta, CosTheta)
%record (Pt) %name Pp
%integer i
%switch VP (XY:YZ)
%real t
   -> VP (Plane)
   VP (XY): %for i = 1,1,Num %cycle
               Pp == V (i)
               t = Pp_x
               Pp_x = CosTheta * t + SinTheta * Pp_y
               Pp_y = -SinTheta * t + CosTheta * Pp_y
            %repeat
            %return
   VP (XZ): %for i = 1,1,Num %cycle
               Pp == V (i)
               t = Pp_x
               Pp_x = CosTheta * t + SinTheta * Pp_z
               Pp_z = -SinTheta * t + CosTheta * Pp_z
            %repeat
            %return
   VP (YZ): %for i = 1,1,Num %cycle
               Pp == V (i)
               t = Pp_y
               Pp_y = CosTheta * t + SinTheta * Pp_z
               Pp_z = -SinTheta * t + CosTheta * Pp_z
            %repeat
%end

%routine Quick Sort (%short A, B)
%short l,u
%record (Polt) %name Pp
   %while a < b %cycle
      l = a; u = b
      Pp == PL(u)
      -> Get
Up:   l = l + 1
      -> Got %if l = u
Get:  -> Up %unless Pp_Depth > PL(l)_Depth
      PL(u) == PL(l)
Down: u = u - 1
      -> Got %if l = u
      -> Down %unless Pp_Depth < PL(u)_Depth
      PL(l) == PL(u)
      -> Up
Got:  PL(u) == Pp
      l = l - 1
      u = u + 1
      %if l - a > b - l %then Quick Sort (u,b) %and b = l %c
                        %else Quick Sort (a,l) %and a = u
   %repeat
%end

%byte %fn Shade (%record (Pt) %name P1, P2, P3)
%byte dp, %real Len
%record (Pt) N,M,L,T1,T2
%real Dot

%integerfn Sign (%name N)
{** SIGN returns the sign (-1 or 1) of a real by inspecting its top bit
{** 
   %result=-1 %if 16_80000000 & Integer(Addr(N)) # 0; %result=1
%end

    T1_x=P1_x-P2_x; T1_y=P1_y-P2_y; T1_z=P1_z-P2_z            {** T1 = P1-P2 **}
    T2_x=P1_x-P3_x; T2_y=P1_y-P3_y; T2_z=P1_z-P3_z            {** T2 = P1-P3 **}
    N_X=T1_Y*T2_Z-T1_Z*T2_Y                         {** N = Cross product of **}
    N_Y=T1_Z*T2_X-T1_X*T2_Z                         {** T1 and T2, ie is the **}
    N_Z=T1_X*T2_Y-T1_Y*T2_X                         {** normal of the poly.  **}
    Len=Sqrt(N_X*N_X+N_Y*N_Y+N_Z*N_Z)               {** Make N a unit vector **}
    %if Len # 0 %start
       N_X=N_X/Len; N_Y=N_Y/Len; N_Z=N_Z/Len
    %finish
    Dot = N_X*Light_X+N_Y*Light_Y+N_Z*Light_Z
    %if Sign (Dot) = - Sign (N_Z) %c
      %then %result = Ambient + IntPt ( (31-Ambient) * |Dot|)
    %result = Ambient
%end

%routine Init
%const %integer PMax = 200
%const %string (30) File = "ram_1:Dsd"
%real A
%integer PtNum
%record (Pt) %array P (1:PMax)
%record (Pt) %name Pp
%record (Polt) %name Pt

%short %array Ad ('a':'z')
   PrintString ("Opening ".File."..."); newline
   Open Input (3,File)
   Select Input (3)
   PtNum = 1
   Read Symbol (j) %until j = '#'
   %cycle
      Read Symbol (j) %until j # ' ' %and j # NL
      %exit %if j = '$'
      Ad (j) = PtNum - 1
      %cycle
         Read Symbol (j) %until j = ':' %or j = '$'
         %exit %if j = '$'
         Pp == P(PtNum)
         Read (Pp_X); Read (Pp_Y); Read (Pp_Z)
         PtNum = PtNum + 1
      %repeat
   %repeat
   Write(PtNum,0);Printstring(" Points, and ")
   Num Poly = -1
   Read Symbol (j) %until j = '#'
   %cycle
      Read Symbol (j) %until j = ':' %or j = '$'
      %exit %if j = '$'
      NumPoly = NumPoly + 1
      Pt == P1(NumPoly)
      Read (Pt_Num)
      %for j = 1,1,Pt_Num %cycle
         ReadSymbol (i) %until i # ' ' %and i # NL
         Read (k)
         k = k + Ad (i)
         Pt_V(j) = P(k)
      %repeat
   %repeat
   Read Symbol (j) %until j = '#'
   Read (Num Ships)
   %for i = 1,1,Num Ships %cycle
      Sp == SRec (i)
      Read (Sp_CX); Read (Sp_CY); Read (Sp_Dist)
      Read (xv); Sp_CsX = Cos(xv*Rad); Sp_SnX = Sin(xv*Rad)
      Read (yv); Sp_CsY = Cos(yv*Rad); Sp_SnY = Sin(yv*Rad)
      Read (zv); Sp_CsZ = Cos(zv*Rad); Sp_SnZ = Sin(zv*Rad)
   %repeat
   Close Input
   Select Input (0)
   Write(NumPoly,0);PrintString (" Polygons read in"); newline
%end

%routine Stuff
   Printsymbol(13);PrintSymbol(27);PrintSymbol('t')
   PrintString (" X = ");Write(xv,0)
   PrintString (" Y = ");Write(Yv,0)
   PrintString (" Z = ");Write(Zv,0)
   Printstring ("  Dist = ");Write (Sp_Dist,0)
   PrintString("  CX = ");Write(Sp_CX,0)
   PrintString("  CY = ");Write(Sp_CY,0)
   PrintString("  Inc = ");Write(An,0)
%end

%routine Up
   PrintSymbol(27);PrintSymbol('A')
   PrintSymbol(13);PrintSymbol(27);PrintSymbol('t')
%end
 
%routine Set up Stars
%short j
   %for i = 1,1,Max Stars %cycle
      Stars (i,1) = Random Int (1,686)
      Stars (i,2) = Random Int (1,510)
   %repeat     
%end

%halfintegerarray cmap(0:255)

%routine Set Up
%integer i
%integer z = 0
  Offset (0,0)
  Colour (White)
  %for i = 0, 16, 240 %cycle
     CMap (i+0)  = z
     CMap (i+1)  = 31
     CMap (i+2)  = 31<<5
     CMap (i+3)  = 31<<5+31
     CMap (i+4)  = 31<<10
     CMap (i+5) = 31<<10+31
     CMap (i+6) = 31<<10+31<<5
     CMap (i+7) = 31<<10+31<<5+31
     CMap (i+8) = 31<<10+31<<5+31
     CMap (i+9) = 31<<10+31<<5
     CMap (i+10) = 31<<10+31
     CMap (i+11) = 31<<10
     CMap (i+12) = 31<<5+31
     CMap (i+13) = 31<<5
     CMap (i+14) = 31
     CMap (i+15) = z
  %repeat
  update colour map(cmap(0))
%end

%routine Mix Colour (%short Col, Red, Green, Blue)
   CMap(Col)=Red+Green<<5+Blue<<10
%end

%routine VClear
   Print Symbol (27); Print Symbol (118)
%end

%routine Clear All
   VClear
   Clear
%end

%const %byte %c
MsNone = 0, MsL    = 1, MsM    = 2, MsLM   = 3, MsR    = 4,
MsLR   = 5, MsMR   = 6, MsLMR  = 7

i=iff open frame("starwars", "Star Wars", 3)
Setup
Initialise Random
Set Up Stars
StB = Addr (Stars(1,1))
StT = Addr (Stars(Max Stars,2))
newline
PrintString ("Star Wars thing"); newline; newline
Printline("MsR,L,M = Rotate X,Y,Z")
Printline("Move Mouse to move ship, if Moving option selected")
Printline("h = Hidden Line On/Off")
Printline("s = Shading On/Off")
Printline("z = Shade Line On/Off")
Printline("m = Moving On/Off")
Printline("l = Enter Light Vector")
Printline("a = Enter Increment Angle")
Printline("  = Negate Current Angle")
Printline("c = Enter Ship X,Y")
Printline("No Edge Clipping")
Init
Len = Sqrt(Lx*Lx + Ly*Ly + Lz*Lz)
Light_X = Lx/Len; Light_Y = Ly/Len; Light_Z = Lz/Len
%for i = 1,1,7 %cycle
   j = i<<5
   Mix Colour (j+k,(i&1)*k,((i>>1)&1)*k,((i>>2)&1)*k) %for k = 0,1,31
%repeat
mousex = 0; mousey = 0
convert
sa = sin(An*Rad)
ca = cos(An*Rad)
Sp == SRec(1)
Stuff
%cycle
   %for ships = 1,1,Num Ships %cycle
      Sp == SRec (ships)
      Sc = 200/Sp_Dist
      %for i = 0,1,Num Poly %cycle
         P2(i) = P1(i) 
         PL(i) == P2(i)
         Pp == P2(i)
         PV == Pp_V
         Rotate (YZ,PV,Pp_Num,sp_snx,sp_csx)
         Rotate (XZ,PV,Pp_Num,sp_sny,sp_csy)
         Rotate (XY,PV,Pp_Num,sp_snz,sp_csz)
         Max = PV(1)_Z
         %for j = 1,1,Pp_Num %cycle
            Max = PV(j)_Z %if PV(j)_Z > Max
         %repeat
         Pp_Depth = Int(Max)
      %repeat
      Quick Sort (0, NumPoly)
      CX = Sp_CX
      CY = Sp_CY + DS
      %for i = 0,1,NumPoly %cycle
         Pp == PL (i)
         PV == Pp_V
         %if Hidden = True %start
            %if Shading = True %start
               %if Pp_Num >= 3 %start
                  Colour (224+Shade(PV(1), PV(2), PV(3)))
                  Poly (Int(PV(j)_X*Sc+CX), 
                       Int(PV(j)_Y*Sc+CY)) %for j = 1,1,Pp_Num
                  Close Poly
               %finish
               %if Shade Line = True %and Sp_Dist <= LineDist %start
                  Colour (Black)
             Line(Int(PV(j)_X*SC+CX),Int(PV(j)_Y*SC+CY),
                  Int(PV(j+1)_X*SC+CX),Int(PV(j+1)_Y*SC+CY)) %for j=1,1,Pp_Num-1
             Line(Int(PV(1)_X*SC+CX),Int(PV(1)_Y*SC+CY),
                  Int(PV(Pp_Num)_X*SC+CX),Int(PV(Pp_Num)_Y*SC+CY))
               %finish
            %else
               %if Pp_Num >= 3 %start
                  Colour (Black)
                  Poly (Int(PV(j)_X*Sc+CX), 
                        Int(PV(j)_Y*Sc+CY)) %for j = 1,1,Pp_Num
                  Close Poly
               %finish
               Colour (White)
          Line(Int(PV(j)_X*SC+CX),Int(PV(j)_Y*SC+CY),
               Int(PV(j+1)_X*SC+CX),Int(PV(j+1)_Y*SC+CY)) %for j=1,1,Pp_Num-1
          Line(Int(PV(1)_X*SC+CX),Int(PV(1)_Y*SC+CY),
               Int(PV(Pp_Num)_X*SC+CX),Int(PV(Pp_Num)_Y*SC+CY))
            %finish
         %else
          Colour (White)
          Line(Int(PV(j)_X*SC+CX),Int(PV(j)_Y*SC+CY),
               Int(PV(j+1)_X*SC+CX),Int(PV(j+1)_Y*SC+CY)) %for j=1,1,Pp_Num-1
          Line(Int(PV(1)_X*SC+CX),Int(PV(1)_Y*SC+CY),
               Int(PV(Pp_Num)_X*SC+CX),Int(PV(Pp_Num)_Y*SC+CY))
         %finish
      %repeat
   %repeat
   %cycle
         MB = Get Mouse
         ii = Test Symbol
   
         %if ii # -1 %start
            %cycle; %repeat %until Test Symbol = -1
            %if ii = ' ' %start
               an = -an
               Sa = -Sa
               Change = False
            %finishelsec
            %if ii = 'm' %start
               Moving = 1 - Moving
            %finishelsec
            %if ii = 's' %start
               Change = False
               Shading = 1-Shading
               Hidden = True %if Shading = True
            %finish %elsec
            %if ii = 'z' %start
               Shade Line = 1-Shade Line
               Change = False
            %finishelsec
            %if ii = 'h' %start
               Change = False
               Hidden = 1-Hidden
               Shading = False %if Hidden = False
            %finish %elsec
            %if ii = 'a' %start
               Change = False
               PrintSymbol(13);PrintSymbol(27);PrintSymbol('t')
               Prompt ("Increment Angle : ");read (an);Up
               sa = sin(an*rad); ca = cos(an*rad)
            %finishelsec
            %if ii = 'l' %start
               Change = False
               PrintSymbol(13);PrintSymbol(27);PrintSymbol('t')
               Prompt ("Light_X : ");read(Lx);Up
               Prompt ("Light_Y : ");read(LY);Up
               Prompt ("Light_Z : ");read(LZ);Up
               Len = Sqrt(Lx*Lx + Ly*Ly + Lz*Lz)
               %if Len # 0 %start
                  Light_X = Lx/Len; Light_Y = Ly/Len; Light_Z = Lz/Len
               %finish
            %finishelsec
            %if ii = 'c' %start
               Change = False
               PrintSymbol(13);PrintSymbol(27);PrintSymbol('t')
               Prompt ("CentreX : ");read (sp_cx);Up
               Prompt ("CentreY : ");read (sp_cy);Up
            %finish
         %finishelsec
         %if MB # 0 %and MB # MsLR %start
         %if MB = MsLM %start
            Change = False
            Sp_Dist = Sp_Dist - 10 %unless Sp_Dist <= 10
            Sc = 200/Sp_Dist
         %finish %elsec
         %if MB = MsMR %start
            Change = False
            Sp_Dist = Sp_Dist + 10 %and Sc = 200/Sp_Dist
         %finish %elsec
         %if MB = MsLMR %then %stop
         %if MB = MsR %start
               zv = zv + an 
               zv = zv - 360 %if zv > 360
               zv = 360 + zv %if zv < -360
         %finishelsec
         %if MB = MsM %start
               Yv = Yv + an
               yv = yv - 360 %if yv > 360
               yv = 360 + yv %if yv < -360
         %finishelsec
         %if MB = MsL %start
               Xv = Xv + an
               xv = xv - 360 %if xv > 360
               xv = 360 + xv %if xv < -360
         %finish
       %finish
       %if Moving = True %start
         Convert
         i = mx - ox; j = my - oy
         sp_cx = (sp_cx + i) & 1023
         sp_cy = (sp_cy + j) & 1023
         ii = 1 %if i # 0 %or j # 0
       %finish
       Stuff %if (MB # 0 %and MB # MsLR) %or ii # -1
   %repeatuntil (MB # 0 %and MB # MsLR) %or ii # -1
%repeat
iff close frame
%endofprogram
