unit dp1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  dddd, StdCtrls, ExtCtrls,
  d3dtypes,d3d,d3dcaps,ddraw,
  s_mathPack,primitives;

type
  TForm1 = class(TForm)
    QD: TDDDD;
    RadioGroup1: TRadioGroup;
    procedure QDInit(Sender: TObject; fNeedChange: Boolean);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
    AgeT:Int64;                       //時刻
    Tex:Array[0..0] of TDDDDTexture;  //最初はテクスチャ一杯使うつもりだったんだけど(^^;)
    Rend:TPrimitiveRenderer;          //キモとなるレンダラオブジェクト

    procedure RotationDemo;           //回転デモ
    procedure BlendDemo;              //半透明デモ
    procedure DeformDemo;             //変形デモ
    procedure ColorChangeDemo;        //色変えデモ

    procedure AppIdle(sender:TObject; var done:Boolean);
    procedure SetupIM;
    procedure Flip;
  end;

const
  P_BOSS2 = 0;

var
  Form1: TForm1;

implementation


//回転デモ
procedure TForm1.RotationDemo;
var
  dir,right:TVector2D;
begin
  dir:=NowRot2D(Vector2D(0,-128),AgeT);
  right:=Vector2D(-dir.Y,dir.X);

  //パターンP_BOSS2 を、
  //  v[]で示される四角形の範囲に、
  //  Z値 = 0(一番奥)で、
  //  αブレンドを行わず(bmDecal)
  //  そのままの色で($FFFFFFFF) 書きこむ
  Rend.PushPattern2D(P_BOSS2,
    NowSub2D(NowAdd2D(Vector2D(200,200),dir),right),
    NowAdd2D(NowAdd2D(Vector2D(200,200),dir),right),
    NowSub2D(NowSub2D(Vector2D(200,200),dir),right),
    NowAdd2D(NowSub2D(Vector2D(200,200),dir),right),
    0, bmDecal, $FFFFFFFF);

end;


//アルファブレンドデモ
procedure TForm1.BlendDemo;
var
  dir,right:TVector2D;
  i:Integer;
  Col:Array[0..2] of DWord;
begin
  Col[0]:=$FFFF0000;
  Col[1]:=$FF00FF00;
  Col[2]:=$FF0000FF;


  for i:=0 to 2 do begin
    dir:=NowRot2D(Vector2D(0,-200),AgeT * (i+1));
    right:=Vector2D(-dir.Y,dir.X);



    Rend.PushPattern2D(P_BOSS2,
      NowSub2D(NowAdd2D(Vector2D(200,200),dir),right),
      NowAdd2D(NowAdd2D(Vector2D(200,200),dir),right),
      NowSub2D(NowSub2D(Vector2D(200,200),dir),right),
      NowAdd2D(NowSub2D(Vector2D(200,200),dir),right),
      0, bmAdd, Col[i]);

  end;
end;


//変形デモ
procedure TForm1.DeformDemo;
begin

  Rend.PushPattern2D(P_BOSS2,
    NowAdd2D(Vector2D(200+128,200+128), NowRot2D(Vector2D(0,64),AgeT * 2)),
    NowAdd2D(Vector2D(200-128,200+128), NowRot2D(Vector2D(0,64),AgeT Shr 1 * 3)),
    NowAdd2D(Vector2D(200+128,200-128), NowRot2D(Vector2D(0,64),AgeT )),
    NowAdd2D(Vector2D(200-128,200-128), NowRot2D(Vector2D(0,64),AgeT Shr 1)),
    0, bmDecal, $FFFFFFFF);
end;



//色変えデモ
procedure TForm1.ColorChangeDemo;
  function HSV2RGB(hi,si,vi:Integer):DWord;
  var
    h,s,v,Cr,Cb,r,g,b:Extended;
    ri,gi,bi:Integer;
  begin
    h:= (hi - 128.0)/128.0 * Pi;  // ±Pi
    s:= si / 512.0;
    v:= vi / 256.0;
    Cr:= s * Cos(h);
    Cb:= s * Sin(h);
    r := (v + 1.4026*Cr) * 256.0;
    g := (v - 0.7144*Cr - 0.3444*Cb) * 256.0;
    b := (v             + 1.7730*Cb) * 256.0;

    ri:=Trunc(r);
    if ri > 255 then ri:=255;
    if ri < 0   then ri:=0;
    gi:=Trunc(g);
    if gi > 255 then gi:=255;
    if gi < 0   then gi:=0;
    bi:=Trunc(b);
    if bi > 255 then bi:=255;
    if bi < 0   then bi:=0;

    result:=$FF000000 Or (DWord(ri) Shl 16) Or (DWord(gi) Shl 8) Or DWord(bi);
  end;
begin
  Rend.PushPatternRect(P_BOSS2, SingleRect(200-128,200-128,200+128,200+128),0,bmDecal, HSV2RGB((AgeT Shr 3) And 255,192,255));
end;

















//メインループ
procedure TForm1.AppIdle(sender:TObject; var done:Boolean);
var
  clearRect:D3DRect;
  t,f:Int64;
begin
  //画面クリア
  with clearRect do begin
    x1:=0;
    y1:=0;
    x2:=QD.BackBuffer.Width;
    y2:=QD.BackBuffer.Height;
  end;

  QD.D3DDevice.Clear(1, @clearRect, D3DCLEAR_ZBUFFER + D3DCLEAR_TARGET,  $FF000000,1.0,0);

  QueryPerformanceFrequency(f);
  QueryPerformanceCounter(t);
  AgeT:=t * 1000 div f;

  //デモる
  Case RadioGroup1.ItemIndex of
    0: RotationDemo;
    1: BlendDemo;
    2: DeformDemo;
    3: ColorChangeDemo;
  end;

  //レンダリング
  QD.D3DDevice.BeginScene;

  Rend.Render;

  QD.D3DDevice.EndScene;


  //フリップ(QD.Flipじゃない点に注意)
  Flip;

  Done:=False;
end;


//バックバッファの内容を転送
//ウィンドウモードのアプリで、ウィンドウの一部をDirectX用に使う場合は、こんな感じでやるといいっすよ
procedure TForm1.Flip;
var
  dr:TRect;
  fx:DDBLTFX;
begin
  //表示枠の画面上の位置を算出
  dr.TopLeft:=ClientToScreen(Point(8,8));
  dr.BottomRight:=ClientToScreen(Point(408,408));

  //バックバッファからプライマリサーフェスに転送
  ZeroMemory(@fx,sizeof(fx));
  fx.dwSize:=sizeof(fx);
  QD.FrontBuffer.Blt(QD.BackBuffer,dr, Rect(0,0,400,400), DDBLT_WAIT, fx);
end;



//IMの設定
procedure TForm1.SetupIM;
var
  viewParam:D3DVIEWPORT7;
begin
  //ビューポートの特性
  with viewParam do begin
    dwX:=0; dwY:=0;                        //レンダリングが施される左上座標
    dwWidth:=400;       //レンダリングが施される範囲
    dwHeight:=400;
    dvMinZ:=0;
    dvMaxZ:=1.0;
  end;

  //ビューポートの特性を指定する
  QD.D3DDevice.SetViewport(@viewParam);
end;





{$R *.DFM}

//初期化
procedure TForm1.QDInit(Sender: TObject; fNeedChange: Boolean);
var
  IMGPATH:String;
begin
  //演算パッケージの初期化
  NowInit;

  //変数の初期化
  AgeT:=0;

  //環境設定
  if MessageDlg('HAL使うかい？',mtConfirmation,[mbYes,mbNo],0) <> mrYes then
    QD.D3DOptions:=[DontUseTnLHAL,DontUseHAL,DontUseMMX,MakeZBuffer];

  QD.WindowMode(400,400);

  SetupIM;
  Rend:=TPrimitiveRenderer.Create(QD,16,1); //16個までのプリミティブ、1個までのパターンの登録を許可
  Rend.ZMax:=2;


  //テクスチャの読みこみ
  IMGPATH:=ExtractFilePath(Application.ExeName);

  Tex[0]:=TDDDDTexture.Create(QD, 256,256,0,'');
  Tex[0].LoadBMP(IMGPATH + 'boss2.bmp');
  Tex[0].ColorKey:=Tex[0].Pixels[0,0];
  Rend.SetPattern(P_BOSS2,Tex[0],Rect(0,0,256,256));  //P_BOSS2(=0)番のパターンとして、登録

  //メインループ取りつけ
  Application.OnIdle:=AppIdle;
end;



end.
