[Back to EGAVGA SWAG index] [Back to Main SWAG index] [Original]

    { Updated EGAVGA.SWG on May 26, 1995 }

    {
    From: ss8913@u.cc.utah.edu (Scott Stone)

    Well, here it is.  A version of the unit that should calculate stuff
    properly. :)  Also, it uses DOUBLE precision instead of REAL.  If it
    won't work on your system (should, with the coprocessor-emulation
    directive in there), then just change all the DOUBLEs back to REALs.

    }
    Unit Graph3d; {Version 0.02 1/12/95}

    {Written 1/7/95 by Scott Stone <scott.stone@m.cc.utah.edu>
     I wrote this because nobody is willing to help a newbie who lacks this
     info, so go ahead and use it freely - I wouldn't mind a mention in your
     credits, however! }

    {Keep in mind, all procedures that require inputs of an angular measurement
     require the measurement in DEGREES, due to the cosine/sine tables involved}

    {This version uses DOUBLE precision, hence the new compiler directive.
     It also fixes the bug that prevents the previous version from working.}

    Interface
    {$N+}

    Var
      sint,cost : array [0..359] of double;

    function rd(radians : double) : double;
    function dr(degrees : double) : double;
    procedure maketables;
    Procedure Rotatexy(ra : integer; ox,oy : double; var nx,ny : double);
    Procedure Rotatexyz(rx,ry,rz : integer; ox,oy,oz : double; var nx,ny,nz :
    double);
    Procedure Rotate3X(rx : integer; ox,oy,oz : double; var nx,ny,nz : double);
    Procedure Rotate3Y(ry : integer; ox,oy,oz : double; var nx,ny,nz : double);
    Procedure Rotate3Z(rz : integer; ox,oy,oz : double; var nx,ny,nz : double);
    Procedure C32(ox,oy,oz : double; ep : integer; var nx,ny : integer);
    function arccos(ca : double) : double;
    Function A2V(i1,j1,k1,i2,j2,k2 : double) : double;

    Implementation

    Function RD (radians : double) : double; {Converts Radians ==>> Degrees}
    Begin
      rd:=((180*radians)/pi);
    End;

    Function DR (degrees : double) : double; {Converts Degrees =>> Radians}
    Begin
      dr:=abs(degrees)*pi/180.0;
    End;

    Procedure MakeTables; {Makes Sine/Cosine tables for faster lookups}
    Var
      cc : integer;
    Begin                 {Defines SINT & COST - used in terms of degrees}
      for cc:=0 to 359 do
      begin
        sint[cc]:=sin(dr(cc));
        cost[cc]:=cos(dr(cc))
      end;
    end;

    Procedure Rotatexy(ra : integer; ox,oy : double; var nx,ny : double);
    {Rotate a 2-D point about the origin - positive degrees are COUNTERclockwise}
    {RA=amount to rotate, in degrees.  ox,oy = old X,Y.  nx,ny = new X,Y}
    Begin
      nx:=(ox*(cost[ra]))-(oy*(sint[ra]));
      ny:=(ox*(sint[ra]))+(oy*(cost[ra]));
    End;

    Procedure Rotatexyz(rx,ry,rz : integer; ox,oy,oz : double; var nx,ny,nz :
    double);
    {Rotate a 3-D point.  rx,ry,rz=amount to rotate about each axis.}
    {ox,oy,oz = old x,y,z.  nx,ny,nz=new x,y,z}
    Var
      tx,ty,tz : double;
      tx1,ty1,tz1 : double;
    Begin
      {first rotate about X-axis}
      tx:=ox;
      ty:=(oy*(cost[rx]))-(oz*(sint[rx]));
      tz:=(oy*(sint[rx]))+(oz*(cost[rx]));
      {now about the Y-axis}
      tx1:=(tx*(cost[ry]))+(tz*(sint[ry]));
      ty1:=ty;
      tz1:=-(tx*(sint[ry]))+(tz*(cost[ry]));
      {now about the Z-axis}
      nx:=(tx1*(cost[rz]))-(ty1*(sint[rz]));
      ny:=(tx1*(sint[rz]))+(ty1*(cost[rz]));
      nz:=tz1;
    End;

    Procedure Rotate3X(rx : integer; ox,oy,oz : double; var nx,ny,nz : double);
    {Just rotate a 3-D point around X-axis - separates might be faster}
    Begin
      if (rx<>0) then {don't do if rx=0 - might save some speed in some cases}
      begin
        nx:=ox;
        ny:=(oy*(cost[rx]))-(oz*(sint[rx]));
        nz:=(oy*(sint[rx]))+(oz*(cost[rx]))
      end;
    End;

    Procedure Rotate3Y(ry : integer; ox,oy,oz : double; var nx,ny,nz : double);
    Begin
      if (ry<>0) then
      begin
        nx:=(ox*(cost[ry]))+(oz*(sint[ry]));
        ny:=oy;
        nz:=-(ox*(sint[ry]))+(oz*(cost[ry]))
      end;
    end;

    Procedure Rotate3Z(rz : integer; ox,oy,oz : double; var nx,ny,nz : double);
    Begin
      if (rz<>0) then
      begin
        nx:=(ox*(cost[rz]))-(oy*(sint[rz]));
        ny:=(ox*(sint[rz]))+(oy*(cost[rz]));
        nz:=oz
      end;
    End;

    Procedure C32(ox,oy,oz : double; ep : integer; var nx,ny : integer);
    {Converts 3-D point to 2-D point}
    {EP = Expansion Factor - useful for 3-D starfields - set to 1 for doubleism}
    Begin
      nx:=round((ox*ep)/oz);
      ny:=round((oy*ep)/oz); {have to round to integers for screen}
    End; {* Note - Make sure you clip your screen points to fit screen res}

    function arccos(ca : double) : double;
    {While compiling this unit, TP7 said that there was no predefined ARCCOS
     function.  There is a pre-defined ARCTAN function, so this procedure
     finds the ARCCOS in terms of the ARCTAN.  This was the hardest part about
     writing this unit.  Isn't math cool? :)  BTW - if this doesn't work, let
     me know.  Better yet, let me know and tell me why it doesn't work. }

    var
      r,r0,r1 : double;
    begin
      r:=sqrt(1-(abs(sqr(ca))));
      r0:=r/ca;
      r1:=arctan(r0);
      arccos:=r1;
    end;

    Function A2V(i1,j1,k1,i2,j2,k2 : double) : double;
    {Finds angle between two vectors - parameters are vector components}
    Var
      theta : double;
      vm1,vm2 : double;
      dp : double;
      ff : double;
    Begin
      vm1:=sqrt(abs(sqr(i1))+abs(sqr(j1))+abs(sqr(k1)));
      vm2:=sqrt(abs(sqr(i2))+abs(sqr(j2))+abs(sqr(k2)));
      dp:=(i1*i2)+(j1*j2)+(k1*k2);
      ff:=(dp/(vm1*vm2));
      theta:=arccos(ff);
      a2v:=theta;
    End;

    Begin
    End.

[Back to EGAVGA SWAG index] [Back to Main SWAG index] [Original]