(******************************************************************************
*                                  project3                                   *
******************************************************************************)
unit project3;

(*******************************************************************************
*      this unit has 2 instances : the first one is used with the windows      *
*               graphic user interface, and the other does not,                *
*                                                                              *
*             +-------------------------------------------------+              *
*             |  this unit is NOT interfaced to the window GUI, |              *
*             |   for use on a bare screen ONLY - for runTime!  |              *
*             |                ****                             |              *
*             +-------------------------------------------------+              *
*                                                                              *
*this unit handles the 3d -> 2d projections, we use 2 different methods        *
*       of projections :                                                       *
*                                                                              *
*               A : axonometric projections, no perspective due to             *
*                       distance is performed, the general way                 *
*                       we can look at the coordinate system is as             *
*                       follows :                                              *
*                                                                              *
*                               |  z axis                                      *
*                               |                                              *
*                              / \                                             *
*                    x axis   /   \  y axis                                    *
*                                                                              *
*               B : perspective projections : the normal eye perspective       *
*                       projection is performed, we can look at the 3d         *
*                       universe we are refering to as a cube of               *
*                       1000 x 1000 x 1000 integer locations, with             *
*                       the x axis, and y axis parallel to the screen          *
*                       x, y axis respectivly, and the z axis going into       *
*                       the screen.                                            *
*                                                                              *
*                       we will look at the coordinate system as follows :     *
*                                                                              *
*                       ³ Y axis                                               *
*                       ³                                                      *
*                Z axis x------ X axis                                         *
*                                                                              *
*                                                                              *
*******************************************************************************)

interface

uses  
{$ifndef windows}  
   graph,
{$endif}
   hdr3d
   ;

const
        perspective     : boolean = false; 
        {true = perspective, else = axonometric}
{$ifndef windows}
var
    MaxX, MaxY : word;          { In pixels for graphics screen }
    MaxColor   : word;
    GraphDriver           : integer;
    GraphMode             : integer;
{$endif}

procedure calcPoint(p3d : point3d; var psc : screenPoints);
procedure setPerspective;
procedure resetPerspective;
procedure togglePerspective;

implementation

{$ifndef windows}
var 
   oldExitProc           : pointer;

(******************************************************************************
*                                 MyExitProc                                  *
******************************************************************************)
procedure MyExitProc; far;
Begin
  ExitProc := OldExitProc; { Restore exit procedure address }
  CloseGraph;              { Shut down the graphics system }
End; { MyExitProc }

(*******************************************************************************
*                                  StartGraph                                  *
*******************************************************************************)
Procedure StartGraph;
var
  ErrorCode : integer;
Begin
  { when using Crt and graphics, turn off Crt's memory-mapped writes }
  OldExitProc := ExitProc;                { save previous exit proc }
  ExitProc := @MyExitProc;                { insert our exit proc in chain }
  GraphDriver := Detect;                  { use autodetection }
  InitGraph(GraphDriver, GraphMode, '');  { activate graphics }
  ErrorCode := GraphResult;               { error? }
  if ErrorCode <> grOk then
  Begin
    Writeln('Graphics error: ', GraphErrorMsg(ErrorCode));
    Halt(1);
  End;
  MaxColor := GetMaxColor;  { Get the maximum allowable drawing color }
  MaxX := GetMaxX;          { Get screen resolution values }
  MaxY := GetMaxY;
End; { Initialize }

{$endif}

(******************************************************************************
*                                  CalcPoint                                  *
******************************************************************************)
procedure CalcPoint;
 {Calculate screen cordinates of 3d location into screen}

begin with p3d, psc do begin
     if Perspective then begin
          z  := z + HalfWidth;
          if z < 0 then 
            z := 0;
          sX := round((x * z / HalfWidth + HalfWidth) * (MaxX / ScreenWidth));
          sY := round((HalfWidth - y * z / HalfWidth) * (MaxY / ScreenWidth));
     end else begin
          sX := round((HalfWidth + cosine_x * x - cosine_y * y) * (MaxX / ScreenWidth));
          sY := round((HalfWidth - z + sine_x * x + sine_y * y) * (MaxY / ScreenWidth));
     end;
   end; {with}
end; { calcPoint }

(******************************************************************************
*                               setPerspective                                *
******************************************************************************)
procedure setPerspective;
begin
        perspective := true;
end; {setPerspective}

(******************************************************************************
*                              resetPerspective                               *
******************************************************************************)
procedure resetPerspective;
begin
        perspective := false;
end; {resetPerspective}

(******************************************************************************
*                              togglePerspective                              *
******************************************************************************)
procedure togglePerspective;
begin
        perspective := not(perspective);
end; {togglePerspective}

(******************************************************************************
*                                    end.                                     *
******************************************************************************)
{$ifndef windows}
begin
    startGraph;
{$endif}
end.
