Unit GTypes;
Interface
Uses UVector,Matrices;
CONST
  vecsize   = sizeof(tVec);

type
  float  = double;

  OBJId = (F_OBJ_SPHERE,F_LIGHT_OMNI,F_VIEWPORT,F_AMBIENT,F_OBJ_SURF_PLANE,
           F_NULL,F_CAMERA,F_TRI_PLANE,F_TRI,F_QUAD,F_TRANSLATE,F_ROTATE,
           F_SCALE,F_SPOTLIGHT,F_TEXTURE,F_INTER_SPHERE,F_CONE);

  RGB  = record
   R, G, B : float;
  end;

  BRGB = record
   B,G,R : byte;
  end;

  PPlane = ^TPlane;
  TPlane = record
    N : tVec;
    D : float;
  end;

  PSurfDesc = ^TSurfDesc;
  TSurfDesc = record
    Kd, Ks, Ns : float;
    {
      Kd - Коэффициент рассеяния
      Ks - Коэффициент отражения
      Ns - Коэффициент вида отражения
    }
  end;

  PBitPlane = ^TBitPlane;
  TBitPlane = array [0..16384] of BRGB;

  PTexture = ^TTexture;
  TTexture = object
    SizeX       : word;
    SizeY       : word;
    Bits        : PBitPlane;
    Name        : string[13];
    Constructor Init(sx,sy:word);
    Procedure   LoadTGA(fname:string);
    Destructor  Done;virtual;
  end;


  PRay = ^TRay;
  TRay = object
    Org  : TVec;
    Dir  : TVec;
    Constructor Init(aOrg, aDir : tVec);
    Procedure GetPoint(var aP : tVec; aT : float);
  end;

   Procedure SetColor(var aCol : RGB;aR,aG,aB:float);
   Procedure SetPlane(var P : TPLane; aV1, aV2, aV3:tVec);
   Function  Pack24(aCol : RGB):LongInt;
   Procedure LoadRGB(var F:FILE;var aCol:RGB);
   Procedure SaveRGB(var F:FILE;aCol:RGB);
   Procedure CalcTransform(var aT:TTRANSFORM;aV1,aV2,aV3:tVec;r,len:real);
   Procedure CAddMul(var aC:RGB;aM:RGB; mul : float);
Implementation
{TRay}
  Constructor TRay.Init;
  begin
   Org := aOrg;
   Dir := aDir;
  end; {TRay.Init}
  {-----------------------------}
  Procedure TRay.GetPoint;
  begin
    VLinear(aP,Org,Dir,1,aT);
  end;{TRay.GetPoint}
{TTexture}
  Constructor TTexture.Init;
  begin
   SizeX := sx;
   SizeY := sy;
   if (Sx*SY > 16384) then
    begin
      WriteLn('Too large texture');
      Halt(206);
    end;
   GetMem(Bits,SizeX*SizeY*3);
   FillChar(Bits^,SizeX*SizeY*3,0)
  end;
  Destructor  TTexture.Done;
  begin
    FreeMem(Bits,SizeX*SizeY*3);
  end;
  Procedure   TTexture.LoadTGA;
  var
   F  : FILE;
   CC : BRGB;
   nc : boolean;
   i,x,y  : word;
   tmp : longint;
  begin
   Name := FNAme;
   nc := false;
   Assign(F,Fname);
   {$I-}
     Reset(f,1);
   {$I+}
   if IOResult <> 0 then
    begin
     WriteLn('Texture file ',fname,' not found');
     Halt(201);
    end;
   BlockRead(F,TMP,4);
   if tmp <> $20000 then
    begin
     WriteLn('Texture file not TGA: ',fname);
     Close(F);
     Halt(202);
    end;
   for i := 1 to 2 do
    begin
     BlockRead(F,TMP,4);
     if (tmp <> 0) and (tmp<>$18000000) then
      begin
       WriteLn('Texture file not TGA: ',fname);
       Close(F);
       Halt(202);
      end;
    end;
   blockread(f,i,2); if i <> SizeX then nc := true; x := i;
   blockread(f,i,2); if i <> SizeY then nc := true; y := i;
   blockread(f,i,2);
   if i <> 24 then
    begin
     WriteLn('Texture file error bitplane: ',fname);
     Close(F);
     Halt(204);
    end;
   if NC then
    begin
     if (X*Y > 16384) then
      begin
        WriteLn('Too large texture: ',fname);
        Halt(206);
      end;
      FreeMem(Bits,SizeX*SizeY*3);
      GetMem(Bits,X*Y*3);
      FillChar(Bits^,SizeX*SizeY*3,0);
      SizeX:=X;
      SizeY:=Y;
    end;

   for y := SizeY-1 downto 0 do
     for x := 0 to SizeX-1 do
      begin
        BlockRead(F,CC,3);
        Bits^[y*SizeX+X] := CC;
      end;
   Close(F);
  end;
{RGB}
  Procedure SetColor;
  begin
   with aCol do begin R:=aR;G:=aG;B:=aB;end;
  end;{RGB.Init}
  Function Pack24;
  var
    rr,gg,bb : longint;
  begin
    if aCol.R > 1.0 then rr := 255 else rr:=round(aCol.R*255);
    if aCol.G > 1.0 then gg := 255 else gg:=round(aCol.G*255);
    if aCol.B > 1.0 then bb := 255 else bb:=round(aCol.B*255);
    Pack24:=(rr shl 16) + (gg shl 8) + bb;
  end;{RGB.Pack24}
Procedure LoadRGB(var F:FILE;var aCol:RGB);
begin
  BlockRead(F,aCol,sizeof(float)*3);
end;
Procedure SaveRGB(var F:FILE;aCol:RGB);
begin
  BlockWrite(F,aCol,sizeof(float)*3);
end;
Procedure CAddMul(var aC:RGB;aM:RGB; mul : float);
begin
  aC.R := aC.R + aM.R * mul;
  aC.G := aC.G + aM.G * mul;
  aC.B := aC.B + aM.B * mul;
end;

Procedure SetPlane(var P : TPLane; aV1, aV2, aV3:tVec);
var
   u,v : tVec;
begin
 VLinear(u,aV1,aV2,1,-1);
 VLinear(v,aV3,aV2,1,-1);
 VCross(P.N,u,v);
 VNorm(P.N,1);
 P.D := -VDot(P.N,aV1);
end;

Procedure CalcTransform;
var
 zed 	: TPLane;
 v2,v3  : tVec;
 tr2    : TTRANSFORM;
begin
 SetPlane(Zed,aV1,aV2,aV3);
 Compute_Coordinate_Transform(aT,aV1,Zed.N,r,len);
 MInvTransPoint(av1,av1,aT);
 MInvTransPoint(av2,av2,aT);
 VLinear(v2,aV2,aV1,1,-1);
 VNorm(v2,1);
 VSet(v3,0,0,1);
 Compute_Axis_Rotation_Transform(tr2,v3,-ArcCos(v2.X));
 Compose_Transforms(aT,tr2);
end; {CalcTransform}
{-----------------------}
end.