unit imtut2_1;

interface

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

type
  TForm1 = class(TForm)
    DDDD1: TDDDD;
    Timer1: TTimer;
    procedure DDDD1Init(Sender: TObject; fNeedChange: Boolean);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}




//初期化
procedure TForm1.DDDD1Init(Sender: TObject; fNeedChange: Boolean);
var
  viewParam:D3DVIEWPORT7;	//ビューポートを示す情報

  mat:D3DMATRIX;
  Zn,Zf:Single;           //近・遠クリッピング面までの距離
  q:Single;               //クリッピング面の距離で計算される係数

  mtrl:D3DMATERIAL7;      //マテリアルについての情報を格納する構造体
  light:D3DLIGHT7;        //光源に関する情報を格納する構造体
begin
  //ビューポートの特性
  with viewParam do begin
    dwX:=0;                                //レンダリングが施される左上座標
    dwY:=0;
    dwWidth:=DDDD1.BackBuffer.Width;       //レンダリングが施される範囲
    dwHeight:=DDDD1.BackBuffer.Height;
    dvMinZ:=0;					 //Zバッファの有効範囲
    dvMaxZ:=1.0;
  end;

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



  //マトリクスの設定

  //ワールド行列
  with mat do begin
    _11:=1;   _12:=0;   _13:=0;   _14:=0;
    _21:=0;   _22:=1;   _23:=0;   _24:=0;
    _31:=0;   _32:=0;   _33:=1;   _34:=0;
    _41:=0;   _42:=0;   _43:=0;   _44:=1;
  end;
  DDDD1.D3DDevice.SetTransform(D3DTRANSFORMSTATE_WORLD, @mat);

  //ビュー行列 … カメラは Z = -5の位置に
  with mat do begin
    _11:=1;   _12:=0;   _13:=0;   _14:=0;
    _21:=0;   _22:=1;   _23:=0;   _24:=0;
    _31:=0;   _32:=0;   _33:=1;   _34:=0;
    _41:=0;   _42:=0;   _43:=5;   _44:=1;
  end;
  DDDD1.D3DDevice.SetTransform(D3DTRANSFORMSTATE_VIEW, @mat);


  //投影行列 … 画角 = 90度 クリッピング面 (近,遠) = (1.0, 5000.0)
  Zn := 1.0;
  Zf := 5000.0;
  q := Zf / (Zf - Zn);
  with mat do begin
    _11:=1.0; _12:=0;         _13:=0;     _14:=0; //Cot(90/2 deg.) = 1.0
    _21:=0;   _22:=1.0;       _23:=0;     _24:=0; //Cot(90/2 deg.) = 1.0
    _31:=0;   _32:=0;         _33:=q;     _34:=1;
    _41:=0;   _42:=0;         _43:=-q*Zn; _44:=0;
  end;
  DDDD1.D3DDevice.SetTransform(D3DTRANSFORMSTATE_PROJECTION, @mat);


  //マテリアル
  ZeroMemory(@mtrl, sizeof(mtrl));
  with mtrl do begin
    //光が当たってない部分は、暗いクリーム色に近づく
    with dcvAmbient do begin
      a:=1.0; r:=0.3; g:=0.3; b:=0.1;
    end;
    //地の色は、クリーム色
    with dcvDiffuse do begin
      a:=1.0; r:=1.0; g:=1.0; b:=0.5;
    end;
    //白くテカる
    with dcvSpecular do begin
      a:=1.0; r:=1.0; g:=1.0; b:=1.0;
    end;
    //自分で発光したりはしない
    with dcvEmissive do begin
      a:=1.0; r:=0.0; g:=0.0; b:=0.0;
    end;
    //スペキュラ強度(テカり具合)
    dvPower:=50.0;  //金属っぽく、かなりキツ目のハイライト
  end;
  //Direct3Dに渡す
  DDDD1.D3DDevice.SetMaterial(@mtrl);


  //光源…それぞれのパラメータと、マテリアルに指定された値の積が画面に出ます
  ZeroMemory(@light, Sizeof(light));
  with light do begin
    with dcvAmbient do begin
      a:=1.0; r:=1.0; g:=1.0; b:=1.0;
    end;
    with dcvSpecular do begin
      a:=1.0; r:=1.0; g:=1.0; b:=1.0;
    end;
    with dcvDiffuse do begin
      a:=1.0; r:=1.0; g:=1.0; b:=1.0;
    end;

    dltType:=D3DLIGHT_DIRECTIONAL;
    with dvDirection do begin
      x:=0.0; y:=0.0; z:=1.0;
    end;
    dvRange:=10000; //適当に、遠くへ

  end;
  //Direct3Dに渡す
  DDDD1.D3DDevice.SetLight(0, @light);  //0番の光源としてセット
  DDDD1.D3DDevice.LightEnable(0,True);  //0番の光源をEnableにする。


  (* レンダリングステートの設定 *)

  //左回りの面もレンダリング(デフォルトでは左回りの面は裏向き扱いされて描画されない)
  DDDD1.D3DDevice.SetRenderState(D3DRENDERSTATE_CULLMODE, Integer(D3DCULL_NONE));

  //スペキュラを使う
  DDDD1.D3DDevice.SetRenderState(D3DRENDERSTATE_SPECULARENABLE, Integer(True));

end;


//描画
procedure TForm1.Timer1Timer(Sender: TObject);
var
  Vs:Array[0..2] of D3DVertex;  //ポリゴンの座標
  clearRect:D3DRect;            //画面クリア用の矩形

  t:DWord;                      //タイマの値
  s,c:Single;                   //回転用、サイン・コサインの値
  mat:D3DMATRIX;                //三角形を回すための行列

  function MakeV(_x,_y,_z, _nx,_ny,_nz, _tu,_tv:Single):D3DVertex;
  begin
    with result do begin
      x:=_x;
      y:=_y;
      z:=_z;
      nx:=_nx;
      ny:=_ny;
      nz:=_nz;
      tu:=_tu;
      tv:=_tv;
    end;
  end;
begin
  //画面クリア
  with clearRect do begin
    x1:=0;
    y1:=0;
    x2:=DDDD1.BackBuffer.Width;
    y2:=DDDD1.BackBuffer.Height;
  end;



  //頂点座標の設定…頂点と法線ベクトルをセット。テクスチャ座標は、今回は適当
  //             x   y   z    nx  ny   nz      tu  tv
  Vs[0]:=MakeV( 0.0,1.7,0.0, 0.0,0.0,-1.0,    0.0,0.0);
  Vs[1]:=MakeV( 1.0,0.0,0.0, 0.0,0.0,-1.0,    1.0,0.0);
  Vs[2]:=MakeV(-1.0,0.0,0.0, 0.0,0.0,-1.0,    0.0,1.0);


  //ワールド行列の変更、Y軸回りにマルチメディアタイマの値に従って三角形を回転
  t:=GetTickCount;
  s:=Sin(t / 1000.0 * Pi);
  c:=Cos(t / 1000.0 * Pi);

  with mat do begin
    _11:=c;   _12:=0;   _13:=-s;   _14:=0;
    _21:=0;   _22:=1;   _23:= 0;   _24:=0;
    _31:=s;   _32:=0;   _33:= c;   _34:=0;
    _41:=0;   _42:=0;   _43:= 0;   _44:=1;
  end;
  DDDD1.D3DDevice.SetTransform(D3DTRANSFORMSTATE_WORLD, @mat);


  asm finit; end;
  DDDD1.D3DDevice.Clear(1,@clearRect,D3DCLEAR_TARGET+D3DCLEAR_ZBUFFER, $FF000000, 1.0, 0);


  asm finit; end;
  DDDD1.D3DDevice.BeginScene;


  asm finit; end;
  DDDD1.D3DDevice.DrawPrimitive(D3DPT_TRIANGLELIST,D3DFVF_VERTEX,@Vs,3, 0);
  asm finit; end;


  DDDD1.D3DDevice.EndScene;
  asm finit; end;


  DDDD1.Flip;

end;

end.
