unit WinForm;

interface

uses
  System.Drawing, System.Collections, System.ComponentModel,
  System.Windows.Forms, System.Data,
  Microsoft.DirectX, Microsoft.DirectX.Direct3D, Microsoft.DirectX.Direct3DX,
  System.IO;

type
  TWinForm = class(System.Windows.Forms.Form)
  {$REGION 'Designer Managed Code'}
  strict private
    /// <summary>
    /// Required designer variable.
    /// </summary>
    Components: System.ComponentModel.Container;
    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    procedure InitializeComponent;
    procedure TWinForm_KeyUp(sender: System.Object; e: System.Windows.Forms.KeyEventArgs);
  {$ENDREGION}
  strict protected
    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    procedure Dispose(Disposing: Boolean); override;
  private
    { Private Declarations }
  public
    constructor Create;
  private
    urzadzenie: Device;
    siatka    : Mesh ;
    materialy : Array of Material;
    tekstury  : Array of Texture;
    urzadzUtracone : Boolean;
    parametry      : PresentParameters;
  public
    function  InicjujGrafike: Boolean;
    procedure Rysuj;
  private
    procedure UtworzSiatke(sciezka: String);
    procedure RysujSiatke;
    procedure ZwolnijTekstury;
    procedure UstawMacierze;
    procedure UstawSwiatla;
    procedure UstawUrzadzenie;
    procedure ZwolnijZasoby(sender: System.Object; e: EventArgs);
    procedure ResetujUrzadzenie(sender: System.Object; e: EventArgs);
    procedure ZablokujResize(sender: System.Object; e: System.ComponentModel.CancelEventArgs);
 end;

  [assembly: RuntimeRequiredAttribute(TypeOf(TWinForm))]

implementation

{$AUTOBOX ON}

{$REGION 'Windows Form Designer generated code'}
/// <summary>
/// Required method for Designer support -- do not modify
/// the contents of this method with the code editor.
/// </summary>
procedure TWinForm.InitializeComponent;
begin
  // 
  // TWinForm
  // 
  Self.AutoScaleBaseSize := System.Drawing.Size.Create(5, 13);
  Self.ClientSize := System.Drawing.Size.Create(592, 566);
  Self.Name := 'TWinForm';
  Self.Text := 'DirectX.NET Przykład 14';
  Borland.Delphi.System.Include(Self.KeyUp, Self.TWinForm_KeyUp);
end;
{$ENDREGION}

procedure TWinForm.Dispose(Disposing: Boolean);
begin
  if Disposing then
  begin
    if Components <> nil then
      Components.Dispose();
  end;
  inherited Dispose(Disposing);
end;

constructor TWinForm.Create;
begin
  inherited Create;
  //
  // Required for Windows Form Designer support
  //
  InitializeComponent;
  //
  // TODO: Add any constructor code after InitializeComponent call
  //
end;

function TWinForm.InicjujGrafike: Boolean;
var
  trybWyswietlania: DisplayMode;
begin
  try
    trybWyswietlania:=
      Manager.Adapters[Manager.Adapters.Default. Adapter].CurrentDisplayMode;

    parametry:= PresentParameters.Create;
    parametry.BackBufferFormat:= trybWyswietlania.Format;
    parametry.BackBufferWidth := trybWyswietlania.Width;
    parametry.BackBufferHeight:= trybWyswietlania.Height;
    parametry.Windowed := false;

    parametry.SwapEffect := Microsoft.DirectX.Direct3D.SwapEffect.Discard;
    parametry.EnableAutoDepthStencil := true;
    parametry.AutoDepthStencilFormat := DepthFormat.D16;

    urzadzenie:= Device.Create(0, DeviceType.Hardware, Self.Handle,
      CreateFlags.SoftwareVertexProcessing, [parametry]);
    Borland.Delphi.System.Include(urzadzenie.DeviceResizing,Self.ZablokujResize);
    Borland.Delphi.System.Include(urzadzenie.DeviceLost,Self.ZwolnijZasoby);
    Borland.Delphi.System.Include(urzadzenie.DeviceReset,Self.ResetujUrzadzenie);
    UstawUrzadzenie;
    Result:= true;
  except
    on DirectXException do Result:= false;
  end;
end;

procedure TWinForm.UstawUrzadzenie;
begin
  UtworzSiatke('bigship1.x');
end;

procedure TWinForm.ZwolnijZasoby(sender: System.Object; e: EventArgs);
begin
  ZwolnijTekstury;
  siatka.Dispose;
end;

procedure TWinForm.ResetujUrzadzenie(sender: System.Object; e: EventArgs);
begin
  UstawUrzadzenie;
end;

procedure TWinForm.ZablokujResize(sender: System.Object; e: System.ComponentModel.CancelEventArgs);
begin
   e.Cancel := true;
end;

procedure TWinForm.Rysuj;
begin
  if (urzadzenie=nil) then Exit;

  if urzadzUtracone then
  begin
    try
       urzadzenie.TestCooperativeLevel;
    except
      on DeviceLostException do;  //Nie rób nic
      on DeviceNotResetException do
        begin
          try
            //Próbuj odzyskać...
            urzadzenie.Reset([parametry]);
            urzadzUtracone:= false;
          except
            on DeviceLostException do;  //Nie rób nic
          end;
         end;
     end;
  end;

  if urzadzUtracone then Exit;

  urzadzenie.Clear(ClearFlags.Target or ClearFlags.ZBuffer, System.Drawing.Color.White, 1.0, 0);
  urzadzenie.BeginScene;

  UstawMacierze;
  UstawSwiatla;

  RysujSiatke;

  urzadzenie.EndScene;
  try
    urzadzenie.Present;
  except
    on DeviceLostException do
       urzadzUtracone:= true;
  end;
end;

procedure TWinForm.UtworzSiatke(sciezka: String);
var xMaterialy     : Array of ExtendedMaterial;
    i              : integer;
    sciezkaTekstury: String;
begin
  siatka := Mesh.FromFile(sciezka, MeshFlags.SystemMemory, urzadzenie, xMaterialy);
  if (tekstury <> nil) then
  begin
    ZwolnijTekstury();
  end;
  SetLength(tekstury,Length(xMaterialy));
  SetLength(materialy,Length(xMaterialy));
  for i:=0 to Length(xMaterialy)-1 do
  begin
    if (xMaterialy[i].TextureFilename <> nil) then
    begin
      sciezkaTekstury:= System.IO.Path.Combine(
        System.IO.Path.GetDirectoryName(sciezka), xMaterialy[i].TextureFilename);
      tekstury[i]    := TextureLoader.FromFile(urzadzenie, sciezkaTekstury);
    end;
    materialy[i]:= xMaterialy[i].Material3D;
    //Te same właściwości materiału dla składowej
    //otaczającej i rozproszonej
    materialy[i].Ambient:= materialy[i].Diffuse;
  end;
end;

procedure TWinForm.ZwolnijTekstury;
var i: integer;
begin
  if (tekstury <> nil) then
  begin
    exit;
  end;
  for i:= 0 to Length(tekstury) do
  begin
    if (tekstury[i]<>nil) then
    begin
      tekstury[i].Dispose;
    end;
  end;
end;

procedure TWinForm.RysujSiatke;
var i: integer;
begin
  for i:= 0 to Length(materialy)-1 do
  begin
    if (Tekstury[i] <> nil) then
    begin
      urzadzenie.SetTexture(0, tekstury[i]);
    end;
    urzadzenie.Material:= materialy[i];
    siatka.DrawSubset(i);
  end;
end;

procedure TWinForm.UstawMacierze;
var yaw,pitch: real;
begin
  yaw  := Environment.TickCount / 5000.0;
  pitch:= Environment.TickCount / 3120.0;
  urzadzenie.Transform.World:= Matrix.RotationYawPitchRoll(yaw, pitch, 0);
  urzadzenie.Transform.View := Matrix.LookAtLH(Vector3.Create(0, 0, -25),
    Vector3.Create(0, 0, 0), Vector3.Create(0, 1, 0));
  urzadzenie.Transform.Projection:= Matrix.PerspectiveFovLH(Math.PI/4.0, 1.0, 1.0, 50.0);
end;

procedure TWinForm.UstawSwiatla;
begin
  urzadzenie.RenderState.Lighting:= true;
  urzadzenie.Lights[0].Diffuse   := Color.White;
  urzadzenie.Lights[0].Specular  := Color.White;
  urzadzenie.Lights[0].&Type     := LightType.Directional;
  urzadzenie.Lights[0].Direction := Vector3.Create(1, -1, 3);
  urzadzenie.Lights[0].Update();
  urzadzenie.Lights[0].Enabled   := true;
  urzadzenie.RenderState.Ambient := Color.FromArgb(100, 100, 100);
  urzadzenie.RenderState.SpecularEnable:= true;
end;

procedure TWinForm.TWinForm_KeyUp(sender: System.Object; e: System.Windows.Forms.KeyEventArgs);
begin
  if (e.KeyCode = Keys.Escape) then
    Self.Close;
end;

end.
