unit globals;

{$I Init.inc}

{*Unit Globals************************************************************

 Globals, Prototypes, the works...

 Created            : 31/01/93
 Last Change        : 21/06/93
 Revisions          : none

 *************************************************************************}

interface

uses dos,crt;

{*Data Types**************************************************************}

type
  Flt = double;                      { Floating point data type }
  Vec = array[0..2] of Flt;          { xyz vector }
  Point = Vec;                       { xyz point }
  Col = Vec;                         { rgb color }
  RGB = array[0..2] of Byte;

  Matrix =  array[0..3,0..3] of Flt; { A 4x4 transformation matrix}

  TRay = record                      { A ray }
    P : Point;                       { Position }
    D : Vec;                         { Direction (unitized) }
  end;

  PPrim = ^TPrim;
  PSurf = ^TSurf;
  TSurf = record
    kDiff,                            { diffuse refl coefficients (rgb) }
    kSpec,                            { specular refl coefficients (rgb) }
    kAmb,
    kTran : Vec;                      { transmission coefficients (rgb) }
    shine : Flt;
  end;

  PHititem = ^THititem;
  THititem = object
    t     : Flt;
    state : byte;
    Prim  : PPrim;
    next  : PHitItem;
    constructor Init(tval : Flt; stateval : Byte; Item : PPrim);
    destructor Done; virtual;
  end;

  PHitlist = ^THitlist;
  THitlist = object
    Next : PHitItem;
    constructor Init;
    procedure Add(Item : PHitItem);
    function Compare(smallest_t : Flt) : boolean;
    destructor Done; virtual;
  end;

  TPrim = Object
    Next : PPrim;
    Surf : PSurf;
    constructor Init;
    function Intersect(Ray : TRay; var Hitlist : PHitlist) : Byte; virtual;
    procedure Normal(P : Point; var N : Vec); virtual;
    destructor Done; virtual;
  end;

  PImage = ^TImage;
  TImage = object
    F : File;
    xres, yres : word;
    infileopen : boolean;
    Buffer : array[0..2047] of RGB;
    constructor Init(x,y : integer);
    procedure FileOpen(FName : PathStr);
    procedure WriteLine;
    destructor Done;
  end;

  TStats = record
    nrays,
    neyerays,
    nshadowrays,
    nreflectedrays,
    nrefractedrays,
    nintersects,
    nintersectssucceeded,
    sphintersects,
    sphintersectssucceeded,
    plnintersects,
    plnintersectssucceeded,
    qdrintersects,
    qdrintersectssucceeded : Flt;
  end;

const
  { ***** THESE CONSTANTS WILL HAVE TO BE REVIEWED *** }

  rayeps = 0.0000001;
  minweight = 0.05;
  maxlevel = 5;

var
  nroots,
  stats       : TStats;
  Image       : PImage;
  antialias   : Byte;
  InFileName  : PathStr;
  OutFileName : PathStr;
  wcrt        : text;
  tickflag    : boolean;
  con         : text;

const
  A_NONE = 0;
  A_ADAPTIVE = 1;
  A_QUICK = 2;

const
  versionstr = '0.001 Alpha 21/06';

Procedure PrintVec(Str : string; Vector : Vec);
Procedure FinalStatistics;

implementation

{*TPrim*******************************************************************}

Constructor TPrim.Init;
begin
  next := nil;
end;

Function TPrim.Intersect;
begin
end;

Procedure TPrim.Normal;
begin
end;

destructor TPrim.Done;
begin
{  Dispose(Next); }
end;

{*THitlist and THitItem routines*******************************************}

Constructor THititem.Init;

begin
  t := tval;
  state := stateval;
  Prim := item;
end;

Destructor THititem.Done;
begin
end;

Constructor THitlist.Init;

begin
  Next := nil;
end;

Procedure THitlist.Add;

begin
  Item^.next := Next;
  Next := Item;
end;

function THitlist.Compare;

begin
  Compare:=False;
  If next^.t<smallest_t then Compare := true;
end;

Destructor THitlist.Done;

var
  dummy : PHitItem;

begin
  while Next<>nil do
  begin
    Dummy := Next^.next;
    Dispose(Next, done);
    Next := Dummy;
  end;
end;

{*TImage***************************************************************}

constructor TImage.Init;

begin
  xres := x;
  yres := y;
  infileopen := false;
end;

procedure TImage.FileOpen;

var
  Header : Array[0..17] of byte;
  count : byte;

begin

  For count := 0 to 12 do Header[count] := 0;
  Header[2] := $2;
  Header[12] := xres AND $FF;
  Header[13] := xres div 256;
  Header[14] := yres AND $FF;
  Header[15] := yres div 256;
  Header[16] := 24;
  Header[17] := 32;

  assign(F, FName);
  rewrite(F,1);
  infileopen := true;
  BlockWrite(F, Header, 18);

end;

procedure TImage.WriteLine;
begin
  BlockWrite(F, Buffer, 3*xres);
end;

destructor TImage.Done;
begin
  if infileopen then Close(F);
end;

procedure PrintVec;
begin
  write(con, Str); write(con, Vector[0]:5:3,' '); write(con, vector[1]:5:3,' '); writeln(con, vector[2]:5:3,' ');
end;

procedure FinalStatistics;

begin
  clrscr;
  writeln('Finished Rendering ',infilename);
  writeln;
  writeln('Total number of rays           ',stats.nrays:10:0);
  writeln('      number of eye rays       ',stats.neyerays:10:0);
  writeln('      number of reflected rays ',stats.nreflectedrays:10:0);
  writeln;
  writeln('Total number of shadow test    ',stats.nshadowrays:10:0);
  writeln;
  writeln('Average number of rays/pixel   ',((stats.nrays+stats.nshadowrays)/(image^.xres*image^.yres)):5:5);
  writeln;
  writeln('Total number of intersects     ',stats.nintersects:10:0);
  if stats.sphintersects>0 then
  writeln('Sphere                         ',stats.sphintersects:10:0);
  if stats.plnintersects>0 then
  writeln('Plane                          ',stats.plnintersects:10:0);
  if stats.qdrintersects>0 then
  writeln('Quadric                        ',stats.qdrintersects:10:0);
  writeln;
  writeln('Total number of hits           ',stats.nintersectssucceeded:10:0);
  if stats.sphintersectssucceeded>0 then
  writeln('Sphere                         ',stats.sphintersectssucceeded:10:0);
  if stats.plnintersectssucceeded>0 then
  writeln('Plane                          ',stats.plnintersectssucceeded:10:0);
  if stats.qdrintersectssucceeded>0 then
  writeln('Quadric                        ',stats.qdrintersectssucceeded:10:0);
  writeln;
  writeln;
end;

begin

  {*** con -> stdout ***********************************************}

  Assign(con,'');
  rewrite(con);

  {*** init var's *** could be in startup **************************}

  tickflag := True;
  with stats do
  begin
     nrays := 0;
     neyerays := 0;
     nreflectedrays := 0;
     nshadowrays := 0;
     nintersects := 0;
     nintersectssucceeded := 0;
     sphintersects := 0;
     sphintersectssucceeded := 0;
     plnintersects := 0;
     plnintersectssucceeded := 0;
     qdrintersects := 0;
     qdrintersectssucceeded := 0;
  end;

end.

